commit 359d7bc29c9555b18bad16cbb78bd44875abc9dc
parent fa7cef2df75c940994f4a700b317645034864b26
Author: Arun Prakash Jana <engineerarun@gmail.com>
Date: Wed, 8 Sep 2021 19:14:05 +0530
Directory-specific sort order
Diffstat:
| M | README.md | | | 1 | + |
| M | nnn.1 | | | 10 | ++++++++++ |
| M | src/nnn.c | | | 74 | +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++------- |
3 files changed, 78 insertions(+), 7 deletions(-)
diff --git a/README.md b/README.md
@@ -78,6 +78,7 @@ It runs smoothly on the Pi, [Termux](https://www.youtube.com/embed/AbaauM7gUJw)
- Case-insensitive version (_aka_ natural) sort
- By name, access/change/mod (default) time, size, extn
- Reverse sort
+ - Directory-specific ordering
- Mimes
- Preview hovered files in FIFO-based previewer
- Open with desktop opener or specify a custom opener
diff --git a/nnn.1 b/nnn.1
@@ -127,6 +127,7 @@ supports the following options:
.Fl "T key"
sort order
keys: 'a'u / 'd'u / 'e'xtension / 'r'everse / 's'ize / 't'ime / 'v'ersion
+ capitalize to reverse (except 'r')
.Pp
.Fl u
use selection if available, don't prompt to choose between selection and hovered entry
@@ -429,6 +430,15 @@ separated by \fI;\fR:
Online docs: https://github.com/jarun/nnn/tree/master/plugins
.Ed
.Pp
+\fBNNN_ORDER:\fR directory-specific sort key.
+.Bd -literal
+ export NNN_ORDER='t:/home/user/Downloads;S:/tmp'
+
+ NOTE: Sort keys can be a/d/e/r/s/t/v (see program option -T).
+ Capitalize to reverse (except 'r').
+ Path must be absolute.
+.Ed
+.Pp
\fBNNN_COLORS:\fR string of color numbers for each context, e.g.:
.Bd -literal
# 8 color numbers:
diff --git a/src/nnn.c b/src/nnn.c
@@ -166,6 +166,9 @@
#define ISODD(x) ((x) & 1)
#define ISBLANK(x) ((x) == ' ' || (x) == '\t')
#define TOUPPER(ch) (((ch) >= 'a' && (ch) <= 'z') ? ((ch) - 'a' + 'A') : (ch))
+#define TOLOWER(ch) (((ch) >= 'A' && (ch) <= 'Z') ? ((ch) - 'A' + 'a') : (ch))
+#define ISUPPER_(ch) ((ch) >= 'A' && (ch) <= 'Z')
+#define ISLOWER_(ch) ((ch) >= 'a' && (ch) <= 'z')
#define CMD_LEN_MAX (PATH_MAX + ((NAME_MAX + 1) << 1))
#define ALIGN_UP(x, A) ((((x) + (A) - 1) / (A)) * (A))
#define READLINE_MAX 256
@@ -430,9 +433,11 @@ static int fifofd = -1;
static uint_t idletimeout, selbufpos, selbuflen;
static ushort_t xlines, xcols;
static ushort_t idle;
-static uchar_t maxbm, maxplug;
+static uchar_t maxbm, maxplug, maxorder;
+static uchar_t cfgsort[CTX_MAX + 1];
static char *bmstr;
static char *pluginstr;
+static char *orderstr;
static char *opener;
static char *editor;
static char *enveditor;
@@ -457,6 +462,7 @@ static struct entry *pdents;
static blkcnt_t dir_blocks;
static kv *bookmark;
static kv *plug;
+static kv *order;
static uchar_t tmpfplen, homelen;
static uchar_t blk_shift = BLK_SHIFT_512;
#ifndef NOMOUSE
@@ -684,8 +690,9 @@ static const char * const messages[] = {
#define NNN_MCLICK 8
#define NNN_SEL 9
#define NNN_ARCHIVE 10
-#define NNN_HELP 11 /* strings end here */
-#define NNN_TRASH 12 /* flags begin here */
+#define NNN_ORDER 11
+#define NNN_HELP 12 /* strings end here */
+#define NNN_TRASH 13 /* flags begin here */
static const char * const env_cfg[] = {
"NNN_OPTS",
@@ -699,6 +706,7 @@ static const char * const env_cfg[] = {
"NNN_MCLICK",
"NNN_SEL",
"NNN_ARCHIVE",
+ "NNN_ORDER",
"NNN_HELP",
"NNN_TRASH",
};
@@ -3788,6 +3796,22 @@ static char *get_kv_val(kv *kvarr, char *buf, int key, uchar_t max, uchar_t id)
return NULL;
}
+static int get_kv_key(kv *kvarr, char *val, uchar_t max, uchar_t id)
+{
+ if (!kvarr)
+ return -1;
+
+ if (id != NNN_ORDER) /* For now this function supports only order string */
+ return -1;
+
+ for (int r = 0; kvarr[r].key && r < max; ++r) {
+ if (xstrcmp((orderstr + kvarr[r].off), val) == 0)
+ return kvarr[r].key;
+ }
+
+ return -1;
+}
+
static void resetdircolor(int flags)
{
/* Directories are always shown on top, clear the color when moving to first file */
@@ -4171,13 +4195,19 @@ static void savecurctx(char *path, char *curname, int nextctx)
g_ctx[tmpcfg.curctx].c_cfg = tmpcfg;
- if (ctxr->c_cfg.ctxactive) /* Switch to saved context */
+ if (ctxr->c_cfg.ctxactive) { /* Switch to saved context */
tmpcfg = ctxr->c_cfg;
- else { /* Set up a new context from current context */
+ /* Skip ordering an open context */
+ cfgsort[CTX_MAX] = cfgsort[nextctx];
+ cfgsort[nextctx] = '0';
+ } else { /* Set up a new context from current context */
ctxr->c_cfg.ctxactive = 1;
xstrsncpy(ctxr->c_path, path, PATH_MAX);
ctxr->c_last[0] = ctxr->c_name[0] = ctxr->c_fltr[0] = ctxr->c_fltr[1] = '\0';
ctxr->c_cfg = tmpcfg;
+ /* If already in an ordered dir, clear ordering for the new context and let it order */
+ if (cfgsort[cfg.curctx] == 'z')
+ cfgsort[nextctx] = 'z';
}
tmpcfg.curctx = nextctx;
@@ -5950,7 +5980,13 @@ static int handle_context_switch(enum action sel)
static int set_sort_flags(int r)
{
- bool session = !r;
+ bool session = (r == '\0');
+ bool reverse = FALSE;
+
+ if (ISUPPER_(r) && (r != 'R') && (r != 'C')) {
+ reverse = TRUE;
+ r = TOLOWER(r);
+ }
/* Set the correct input in case of a session load */
if (session) {
@@ -6060,6 +6096,13 @@ static int set_sort_flags(int r)
return 0;
}
+ if (reverse) {
+ cfg.reverse = 1;
+ entrycmpfn = &reventrycmp;
+ }
+
+ cfgsort[cfg.curctx] = (uchar_t)r;
+
return r;
}
@@ -6488,7 +6531,8 @@ static bool browse(char *ipath, const char *session, int pkey)
errexit();
begin:
- /* Can fail when permissions change while browsing.
+ /*
+ * Can fail when permissions change while browsing.
* It's assumed that path IS a directory when we are here.
*/
if (chdir(path) == -1) {
@@ -6533,6 +6577,16 @@ begin:
}
#endif
+ if (cfgsort[cfg.curctx] == 'z')
+ set_sort_flags('c');
+ if (order && (!cfgsort[cfg.curctx] || (cfgsort[cfg.curctx] == 'c'))
+ && ((r = get_kv_key(order, path, maxorder, NNN_ORDER)) > 0)) {
+ set_sort_flags(r);
+ cfgsort[cfg.curctx] = 'z';
+ }
+ if (cfgsort[cfg.curctx] == '0')
+ cfgsort[cfg.curctx] = cfgsort[CTX_MAX];
+
populate(path, lastname);
if (g_state.interrupt) {
g_state.interrupt = cfg.apparentsz = cfg.blkorder = 0;
@@ -8356,6 +8410,12 @@ int main(int argc, char *argv[])
return EXIT_FAILURE;
}
+ /* Parse order string */
+ if (!parsekvpair(&order, &orderstr, NNN_ORDER, &maxorder)) {
+ msg(env_cfg[NNN_ORDER]);
+ return EXIT_FAILURE;
+ }
+
if (!initpath) {
if (arg) { /* Open a bookmark directly */
if (!arg[1]) /* Bookmarks keys are single char */