@@ -58,8 +58,9 @@ Have fun with it! Missing a feature? Want to contribute? Head to the rolling [To | |||||
- [How to](#how-to) | - [How to](#how-to) | ||||
- [add bookmarks](#add-bookmarks) | - [add bookmarks](#add-bookmarks) | ||||
- [copy file paths](#copy-file-paths) | - [copy file paths](#copy-file-paths) | ||||
- [selection shortcuts](#selection-shortcuts) | |||||
- [default copy](#default-copy) | |||||
- [to clipboard](#to-clipboard) | - [to clipboard](#to-clipboard) | ||||
- [when X is missing](#when-x-is-missing) | |||||
- [copy, move, delete files](#copy-move-delete-files) | - [copy, move, delete files](#copy-move-delete-files) | ||||
- [cd on quit](#cd-on-quit) | - [cd on quit](#cd-on-quit) | ||||
- [run custom scripts](#run-custom-scripts) | - [run custom scripts](#run-custom-scripts) | ||||
@@ -104,7 +105,7 @@ Have fun with it! Missing a feature? Want to contribute? Head to the rolling [To | |||||
- Batch rename/move/delete current directory entries in vidir (from moreutils) | - Batch rename/move/delete current directory entries in vidir (from moreutils) | ||||
- Spawn SHELL (fallback sh) in the current directory | - Spawn SHELL (fallback sh) in the current directory | ||||
- Run custom scripts in the current directory | - Run custom scripts in the current directory | ||||
- Copy absolute file paths with/without X (*easy* shell integration) | |||||
- Copy absolute file paths with quotes | |||||
- Change directory at exit (*easy* shell integration) | - Change directory at exit (*easy* shell integration) | ||||
- Open any file in EDITOR (fallback vi) or PAGER (fallback less) | - Open any file in EDITOR (fallback vi) or PAGER (fallback less) | ||||
- Open current directory in a custom GUI file manager | - Open current directory in a custom GUI file manager | ||||
@@ -330,14 +331,13 @@ To lookup keyboard shortcuts at runtime, press <kbd>?</kbd>. | |||||
### Quickstart | ### Quickstart | ||||
1. Install the [utilities required](#file-handling) for your regular activities. | 1. Install the [utilities required](#file-handling) for your regular activities. | ||||
2. Configure file path copy [using X clipboard](#to-clipboard) or [without X](#when-x-is-missing). | |||||
3. Configure [cd on quit](#cd-on-quit). | |||||
4. Optionally open all text files in EDITOR (fallback vi): | |||||
2. Configure [cd on quit](#cd-on-quit). | |||||
3. Optionally open all text files in EDITOR (fallback vi): | |||||
export NNN_USE_EDITOR=1 | export NNN_USE_EDITOR=1 | ||||
5. Run `n`. | |||||
6. Press <kbd>?</kbd> for help on keyboard shortcuts anytime. | |||||
7. For additional functionality [setup custom scripts](#run-custom-scripts). | |||||
4. Run `n`. | |||||
5. Press <kbd>?</kbd> for help on keyboard shortcuts anytime. | |||||
6. For additional functionality [setup custom scripts](#run-custom-scripts). | |||||
### How to | ### How to | ||||
@@ -351,24 +351,7 @@ The bookmark prompt also understands the <kbd>~</kbd> (HOME), <kbd>-</kbd> (last | |||||
#### copy file paths | #### copy file paths | ||||
File paths can be copied to the clipboard or to a specific temporary file (if X is unavailable, for example). When in multi-copy mode, currently copied file paths can be listed by pressing `y`. | |||||
##### to clipboard | |||||
`nnn` can pipe the absolute path of the current file or multiple files to a copier script. For example, you can use `xsel` on Linux or `pbcopy` on OS X. | |||||
Sample Linux copier script: | |||||
#!/bin/sh | |||||
# comment the next line to convert newlines to spaces | |||||
IFS= | |||||
echo -n $1 | xsel --clipboard --input | |||||
export `NNN_COPIER`: | |||||
export NNN_COPIER="/path/to/copier.sh" | |||||
##### selection shortcuts | |||||
Use <kbd>^K</kbd> to copy the absolute path (from `/`) of the file under the cursor to clipboard. | Use <kbd>^K</kbd> to copy the absolute path (from `/`) of the file under the cursor to clipboard. | ||||
@@ -376,6 +359,7 @@ To copy multiple file paths, switch to the multi-copy mode using <kbd>^Y</kbd>. | |||||
- select multiple files one by one by pressing <kbd>^K</kbd> on each entry; or, | - select multiple files one by one by pressing <kbd>^K</kbd> on each entry; or, | ||||
- navigate to another file in the same directory to select a range of files. | - navigate to another file in the same directory to select a range of files. | ||||
- list the currently copied file paths by pressing `y`. | |||||
Pressing <kbd>^Y</kbd> again copies the paths to clipboard and exits the multi-copy mode. | Pressing <kbd>^Y</kbd> again copies the paths to clipboard and exits the multi-copy mode. | ||||
@@ -386,21 +370,15 @@ This is particularly useful if you are planning to copy the whole string to the | |||||
Note that the filename is not escaped. So copying may still fail for filenames having quote(s) in them. | Note that the filename is not escaped. So copying may still fail for filenames having quote(s) in them. | ||||
##### when X is missing | |||||
##### default copy | |||||
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 `DIR/.nnncp`, where `DIR` (by priority) is: | |||||
By default file paths are copied to the temporary file `DIR/.nnncp`, where `DIR` (by priority) is: | |||||
$HOME or, | $HOME or, | ||||
$TMPDIR or, | $TMPDIR or, | ||||
/tmp | /tmp | ||||
`nnn` needs to know X is unavailable: | |||||
export NNN_NO_X=1 | |||||
To see the path to the copy file, run `nnn`, press `?` and look up `NNN_NO_X`. | |||||
Note: despite the name of the environment variable, this method works even if X is available. | |||||
To see the path to the temporary copy file, run `nnn`, press `?` and look up `copy file`. | |||||
Use <kbd>^Y</kbd> and/or <kbd>^K</kbd> to copy file paths as usual. To use the copied paths from the cmdline, use command substitution. For example, if `DIR` above is `/home/user`: | Use <kbd>^Y</kbd> and/or <kbd>^K</kbd> to copy file paths as usual. To use the copied paths from the cmdline, use command substitution. For example, if `DIR` above is `/home/user`: | ||||
@@ -430,7 +408,24 @@ so you can easily copy, move or delete multiple files together: | |||||
mv (ncp) . | mv (ncp) . | ||||
rm (ncp) -rf | rm (ncp) -rf | ||||
Note that you may want to keep quotes disabled in this case. | |||||
Note that you may want to keep quotes disabled (as it is by default) in this case. | |||||
##### to clipboard | |||||
`nnn` can pipe the absolute path of the current file or multiple files to a copier script. For example, you can use `xsel` on Linux or `pbcopy` on OS X. | |||||
Sample Linux copier script: | |||||
#!/bin/sh | |||||
# comment the next line to convert newlines to spaces | |||||
IFS= | |||||
echo -n $1 | xsel --clipboard --input | |||||
export `NNN_COPIER`: | |||||
export NNN_COPIER="/path/to/copier.sh" | |||||
#### copy, move, delete files | #### copy, move, delete files | ||||
@@ -259,11 +259,8 @@ screensaver. | |||||
echo -n $1 | xsel --clipboard --input | echo -n $1 | xsel --clipboard --input | ||||
------------------------------------- | ------------------------------------- | ||||
.Ed | .Ed | ||||
.Pp | |||||
\fBNNN_NO_X:\fR X display is unavailable. Copy file path(s) to \fI$HOME/.nnncp\fR. | |||||
.Bd -literal | |||||
export NNN_NO_X=1 | |||||
.Ed | |||||
.br | |||||
If it's not set, by default file paths are copied to the tmp file \fBDIR/.nnncp\fR, where 'DIR' (by priority) is: \fI$HOME\fR or, \fI$TMPDIR\fR or, \fI/tmp\fR. | |||||
.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. Note that the filename is not escaped. So copying may still fail | names in the shell. Note that the filename is not escaped. So copying may still fail | ||||
@@ -240,28 +240,26 @@ typedef struct { | |||||
/* Settings */ | /* Settings */ | ||||
typedef struct { | typedef struct { | ||||
uint filtermode : 1; /* Set to enter filter mode */ | |||||
uint mtimeorder : 1; /* Set to sort by time modified */ | |||||
uint sizeorder : 1; /* Set to sort by file size */ | |||||
uint apparentsz : 1; /* Set to sort by apparent size (disk usage) */ | |||||
uint blkorder : 1; /* Set to sort by blocks used (disk usage) */ | |||||
uint showhidden : 1; /* Set to show hidden files */ | |||||
uint copymode : 1; /* Set when copying files */ | |||||
uint autoselect : 1; /* Auto-select dir in nav-as-you-type mode */ | |||||
uint showdetail : 1; /* Clear to show fewer file info */ | |||||
uint showcolor : 1; /* Set to show dirs in blue */ | |||||
uint dircolor : 1; /* Current status of dir color */ | |||||
uint metaviewer : 1; /* Index of metadata viewer in utils[] */ | |||||
uint quote : 1; /* Copy paths within quotes */ | |||||
uint noxdisplay : 1; /* X11 is not available */ | |||||
uint color : 3; /* Color code for directories */ | |||||
uint reserved : 15; | |||||
ushort filtermode : 1; /* Set to enter filter mode */ | |||||
ushort mtimeorder : 1; /* Set to sort by time modified */ | |||||
ushort sizeorder : 1; /* Set to sort by file size */ | |||||
ushort apparentsz : 1; /* Set to sort by apparent size (disk usage) */ | |||||
ushort blkorder : 1; /* Set to sort by blocks used (disk usage) */ | |||||
ushort showhidden : 1; /* Set to show hidden files */ | |||||
ushort copymode : 1; /* Set when copying files */ | |||||
ushort autoselect : 1; /* Auto-select dir in nav-as-you-type mode */ | |||||
ushort showdetail : 1; /* Clear to show fewer file info */ | |||||
ushort showcolor : 1; /* Set to show dirs in blue */ | |||||
ushort dircolor : 1; /* Current status of dir color */ | |||||
ushort metaviewer : 1; /* Index of metadata viewer in utils[] */ | |||||
ushort quote : 1; /* Copy paths within quotes */ | |||||
ushort color : 3; /* Color code for directories */ | |||||
} settings; | } settings; | ||||
/* GLOBALS */ | /* GLOBALS */ | ||||
/* Configuration */ | /* Configuration */ | ||||
static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0, 4, 0}; | |||||
static settings cfg = {0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 4}; | |||||
static struct entry *dents; | static struct entry *dents; | ||||
static char *pnamebuf, *pcopybuf; | static char *pnamebuf, *pcopybuf; | ||||
@@ -409,7 +407,7 @@ static void printerr(int linenum) | |||||
{ | { | ||||
exitcurses(); | exitcurses(); | ||||
fprintf(stderr, "line %d: (%d) %s\n", linenum, errno, strerror(errno)); | fprintf(stderr, "line %d: (%d) %s\n", linenum, errno, strerror(errno)); | ||||
if (cfg.noxdisplay && g_cppath[0]) | |||||
if (g_cppath[0]) | |||||
unlink(g_cppath); | unlink(g_cppath); | ||||
exit(1); | exit(1); | ||||
} | } | ||||
@@ -618,8 +616,10 @@ static char *xbasename(char *path) | |||||
/* Writes buflen char(s) from buf to a file */ | /* Writes buflen char(s) from buf to a file */ | ||||
static void writecp(const char *buf, const size_t buflen) | static void writecp(const char *buf, const size_t buflen) | ||||
{ | { | ||||
if (!g_cppath[0]) | |||||
if (!g_cppath[0]) { | |||||
printmsg(messages[STR_COPY_ID]); | |||||
return; | return; | ||||
} | |||||
FILE *fp = fopen(g_cppath, "w"); | FILE *fp = fopen(g_cppath, "w"); | ||||
@@ -2016,8 +2016,8 @@ static int show_help(char *path) | |||||
dprintf(fd, "NNN_IDLE_TIMEOUT: %d secs\n", idletimeout); | dprintf(fd, "NNN_IDLE_TIMEOUT: %d secs\n", idletimeout); | ||||
if (copier) | if (copier) | ||||
dprintf(fd, "NNN_COPIER: %s\n", copier); | dprintf(fd, "NNN_COPIER: %s\n", copier); | ||||
if (getenv("NNN_NO_X")) | |||||
dprintf(fd, "NNN_NO_X: %s (%s)\n", getenv("NNN_NO_X"), g_cppath); | |||||
else if (g_cppath[0]) | |||||
dprintf(fd, "copy file: %s\n", g_cppath); | |||||
if (getenv("NNN_SCRIPT")) | if (getenv("NNN_SCRIPT")) | ||||
dprintf(fd, "NNN_SCRIPT: %s\n", getenv("NNN_SCRIPT")); | dprintf(fd, "NNN_SCRIPT: %s\n", getenv("NNN_SCRIPT")); | ||||
if (getenv("NNN_MULTISCRIPT")) | if (getenv("NNN_MULTISCRIPT")) | ||||
@@ -2890,11 +2890,6 @@ nochange: | |||||
copycurname(); | copycurname(); | ||||
goto begin; | goto begin; | ||||
case SEL_COPY: | case SEL_COPY: | ||||
if (!(cfg.noxdisplay || copier)) { | |||||
printmsg(messages[STR_COPY_ID]); | |||||
goto nochange; | |||||
} | |||||
if (!ndents) | if (!ndents) | ||||
goto nochange; | goto nochange; | ||||
@@ -2910,7 +2905,7 @@ nochange: | |||||
g_buf[r] = '\''; | g_buf[r] = '\''; | ||||
g_buf[r + 1] = '\0'; | g_buf[r + 1] = '\0'; | ||||
if (cfg.noxdisplay) | |||||
if (!copier) | |||||
writecp(g_buf, r + 1); /* Truncate NULL from end */ | writecp(g_buf, r + 1); /* Truncate NULL from end */ | ||||
else | else | ||||
spawn(copier, g_buf, NULL, NULL, F_NOTRACE); | spawn(copier, g_buf, NULL, NULL, F_NOTRACE); | ||||
@@ -2919,7 +2914,7 @@ nochange: | |||||
printmsg(g_buf + 1); | printmsg(g_buf + 1); | ||||
} else { | } else { | ||||
r = mkpath(path, dents[cur].name, newpath, PATH_MAX); | r = mkpath(path, dents[cur].name, newpath, PATH_MAX); | ||||
if (cfg.noxdisplay) | |||||
if (!copier) | |||||
writecp(newpath, r - 1); /* Truncate NULL from end */ | writecp(newpath, r - 1); /* Truncate NULL from end */ | ||||
else | else | ||||
spawn(copier, newpath, NULL, NULL, F_NOTRACE); | spawn(copier, newpath, NULL, NULL, F_NOTRACE); | ||||
@@ -2927,11 +2922,6 @@ nochange: | |||||
} | } | ||||
goto nochange; | goto nochange; | ||||
case SEL_COPYMUL: | case SEL_COPYMUL: | ||||
if (!(cfg.noxdisplay || copier)) { | |||||
printmsg(messages[STR_COPY_ID]); | |||||
goto nochange; | |||||
} | |||||
if (!ndents) | if (!ndents) | ||||
goto nochange; | goto nochange; | ||||
@@ -2964,7 +2954,7 @@ nochange: | |||||
} | } | ||||
if (copybufpos) { /* File path(s) written to the buffer */ | if (copybufpos) { /* File path(s) written to the buffer */ | ||||
if (cfg.noxdisplay) | |||||
if (!copier) | |||||
writecp(pcopybuf, copybufpos - 1); /* Truncate NULL from end */ | writecp(pcopybuf, copybufpos - 1); /* Truncate NULL from end */ | ||||
else | else | ||||
spawn(copier, pcopybuf, NULL, NULL, F_NOTRACE); | spawn(copier, pcopybuf, NULL, NULL, F_NOTRACE); | ||||
@@ -3380,8 +3370,7 @@ int main(int argc, char *argv[]) | |||||
g_tmpfplen = xstrlcpy(g_tmpfpath, "/tmp", MAX_HOME_LEN); | g_tmpfplen = xstrlcpy(g_tmpfpath, "/tmp", MAX_HOME_LEN); | ||||
/* Check if X11 is available */ | /* Check if X11 is available */ | ||||
if (!copier && g_tmpfplen && getenv("NNN_NO_X")) { | |||||
cfg.noxdisplay = 1; | |||||
if (!copier && g_tmpfplen) { | |||||
xstrlcpy(g_cppath, g_tmpfpath, MAX_HOME_LEN); | xstrlcpy(g_cppath, g_tmpfpath, MAX_HOME_LEN); | ||||
xstrlcpy(g_cppath + g_tmpfplen - 1, "/.nnncp", MAX_HOME_LEN - g_tmpfplen); | xstrlcpy(g_cppath + g_tmpfplen - 1, "/.nnncp", MAX_HOME_LEN - g_tmpfplen); | ||||
} | } | ||||
@@ -3409,7 +3398,7 @@ int main(int argc, char *argv[]) | |||||
browse(ipath, ifilter); | browse(ipath, ifilter); | ||||
exitcurses(); | exitcurses(); | ||||
if (cfg.noxdisplay && g_cppath[0]) | |||||
if (g_cppath[0]) | |||||
unlink(g_cppath); | unlink(g_cppath); | ||||
#ifdef LINUX_INOTIFY | #ifdef LINUX_INOTIFY | ||||