Add sort by version number mode - noice - small file browser (mirror / fork from 2f30.org)
 (HTM) git clone git://git.codemadness.org/noice
 (DIR) Log
 (DIR) Files
 (DIR) Refs
 (DIR) README
 (DIR) LICENSE
       ---
 (DIR) commit b2f2a6fe76bdbba48c0174b4f1eb05caf1a74b71
 (DIR) parent 6b1ec1959954145d7942ba3b7e65f5cde30485a1
 (HTM) Author: Lazaros Koromilas <lostd@2f30.org>
       Date:   Mon,  8 Apr 2019 12:48:24 +0300
       
       Add sort by version number mode
       
       Diffstat:
         M Makefile                            |       4 ++--
         M config.def.h                        |       3 +++
         M noice.1                             |       2 ++
         M noice.c                             |      12 ++++++++++--
         A strverscmp.c                        |      47 +++++++++++++++++++++++++++++++
         M util.h                              |       4 ++++
       
       6 files changed, 68 insertions(+), 4 deletions(-)
       ---
 (DIR) diff --git a/Makefile b/Makefile
       @@ -7,9 +7,9 @@ MANPREFIX = $(PREFIX)/man
        #CFLAGS = -g
        LDLIBS = -lcurses
        
       -DISTFILES = noice.c strlcat.c strlcpy.c util.h config.def.h\
       +DISTFILES = noice.c strlcat.c strlcpy.c strverscmp.c util.h config.def.h\
            noice.1 Makefile README LICENSE
       -OBJ = noice.o strlcat.o strlcpy.o
       +OBJ = noice.o strlcat.o strlcpy.o strverscmp.o
        BIN = noice
        
        all: $(BIN)
 (DIR) diff --git a/config.def.h b/config.def.h
       @@ -6,6 +6,7 @@
        int dirorder    = 0; /* Set to 1 to sort by directory first */
        int mtimeorder  = 0; /* Set to 1 to sort by time modified */
        int icaseorder  = 0; /* Set to 1 to sort by ignoring case */
       +int versorder   = 0; /* Set to 1 to sort by version number */
        int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */
        int showhidden  = 0; /* Set to 1 to show hidden files by default */
        int usecolor    = 0; /* Set to 1 to enable color attributes */
       @@ -89,6 +90,8 @@ struct key bindings[] = {
                { 't',            SEL_MTIME },
                /* Toggle case sensitivity */
                { 'i',            SEL_ICASE },
       +        /* Toggle sort by version number */
       +        { 'v',            SEL_VERS },
                { CONTROL('L'),   SEL_REDRAW },
                /* Run command */
                { 'z',            SEL_RUN, "top" },
 (DIR) diff --git a/noice.1 b/noice.1
       @@ -63,6 +63,8 @@ Toggle sort by directory first.
        Toggle sort by time modified.
        .It Ic i
        Toggle case sensitive sort.
       +.It Ic v
       +Toggle sort by version number.
        .It Ic C-l
        Force a redraw.
        .It Ic \&!
 (DIR) diff --git a/noice.c b/noice.c
       @@ -58,6 +58,7 @@ enum action {
                SEL_DSORT,
                SEL_MTIME,
                SEL_ICASE,
       +        SEL_VERS,
                SEL_REDRAW,
                SEL_RUN,
                SEL_RUNARG,
       @@ -308,8 +309,9 @@ entrycmp(const void *va, const void *vb)
                        return b->t - a->t;
                if (icaseorder)
                        return strcasecmp(a->name, b->name);
       -        else
       -                return strcmp(a->name, b->name);
       +        if (versorder)
       +                return strverscmp(a->name, b->name);
       +        return strcmp(a->name, b->name);
        }
        
        void
       @@ -850,6 +852,12 @@ nochange:
                                if (ndents > 0)
                                        mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
                                goto begin;
       +                case SEL_VERS:
       +                        versorder = !versorder;
       +                        /* Save current */
       +                        if (ndents > 0)
       +                                mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
       +                        goto begin;
                        case SEL_REDRAW:
                                /* Save current */
                                if (ndents > 0)
 (DIR) diff --git a/strverscmp.c b/strverscmp.c
       @@ -0,0 +1,47 @@
       +#include <ctype.h>
       +#include <stdlib.h>
       +#include <string.h>
       +#include "util.h"
       +
       +int
       +strverscmp(const char *str1, const char *str2)
       +{
       +        size_t len1 = strlen(str1);
       +        size_t len2 = strlen(str2);
       +        size_t i1 = 0;
       +        size_t i2 = 0;
       +        for (; i1 < len1 && i2 < len2; i1++, i2++) {
       +                char c1 = str1[i1];
       +                char c2 = str2[i2];
       +                if (isdigit(c1) && isdigit(c2)) {
       +                        unsigned long long int num1;
       +                        unsigned long long int num2;
       +                        char *end1;
       +                        char *end2;
       +                        num1 = strtoull(str1 + i1, &end1, 10);
       +                        num2 = strtoull(str2 + i2, &end2, 10);
       +                        DPRINTF_LLU(num1);
       +                        DPRINTF_LLU(num2);
       +                        if (num1 < num2)
       +                                return -1;
       +                        if (num1 > num2)
       +                                return 1;
       +                        i1 = end1 - str1 - 1;
       +                        i2 = end2 - str2 - 1;
       +                        if (i1 < i2)
       +                                return -1;
       +                        if (i1 > i2)
       +                                return 1;
       +                } else {
       +                        if (c1 < c2)
       +                                return -1;
       +                        if (c1 > c2)
       +                                return 1;
       +                }
       +        }
       +        if (len1 < len2)
       +                return -1;
       +        if (len1 > len2)
       +                return 1;
       +        return 0;
       +}
 (DIR) diff --git a/util.h b/util.h
       @@ -5,6 +5,8 @@ size_t strlcat(char *, const char *, size_t);
        size_t strlcpy(char *, const char *, size_t);
        #undef dprintf
        int dprintf(int, const char *, ...);
       +#undef strverscmp
       +int strverscmp(const char *, const char *);
        
        #ifdef DEBUG
        #define DEBUG_FD 8
       @@ -12,9 +14,11 @@ int dprintf(int, const char *, ...);
        #define DPRINTF_U(x) dprintf(DEBUG_FD, #x "=%u\n", x)
        #define DPRINTF_S(x) dprintf(DEBUG_FD, #x "=%s\n", x)
        #define DPRINTF_P(x) dprintf(DEBUG_FD, #x "=0x%p\n", x)
       +#define DPRINTF_LLU(x) dprintf(DEBUG_FD, #x "=%llu\n", x)
        #else
        #define DPRINTF_D(x)
        #define DPRINTF_U(x)
        #define DPRINTF_S(x)
        #define DPRINTF_P(x)
       +#define DPRINTF_LLU(x)
        #endif /* DEBUG */