]> Sergey Matveev's repositories - nnn.git/commitdiff
Directory-specific sort order
authorArun Prakash Jana <engineerarun@gmail.com>
Wed, 8 Sep 2021 13:44:05 +0000 (19:14 +0530)
committerArun Prakash Jana <engineerarun@gmail.com>
Wed, 8 Sep 2021 20:16:22 +0000 (01:46 +0530)
README.md
nnn.1
src/nnn.c

index 52d8d3b50b085ff57e7a8e90ef42be57b1469f1b..baa3c4cbc007bb8865d088e67302fe243fefe7b7 100644 (file)
--- 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
index a172f39cb49bb37080a9eb1736cf8c27a41d9087..d0502c2e4c4ec7e123364e16de94d7f219c2c21f 100644 (file)
--- 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:
index 167fdf3a31fd49bd503ede1efb27167170a109bb..82b3fcf85580053f58be3a0d8e40c83c71b070f4 100644 (file)
--- a/src/nnn.c
+++ b/src/nnn.c
 #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 */