mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Initial path: support sort by disk usage
This commit is contained in:
parent
e54ed037bd
commit
cbefcfd67b
|
@ -66,7 +66,8 @@ I chose to fork because:
|
||||||
- number of items in current directory
|
- number of items in current directory
|
||||||
- full name of currently selected file in 'bar'
|
- full name of currently selected file in 'bar'
|
||||||
- Show details of the currently selected file (stat, file)
|
- Show details of the currently selected file (stat, file)
|
||||||
- Directories first
|
- Disk usage analyzer mode
|
||||||
|
- Directories first (even with sorting)
|
||||||
- Sort numeric names in numeric order
|
- Sort numeric names in numeric order
|
||||||
- Case-insensitive alphabetic content listing instead of upper case first
|
- Case-insensitive alphabetic content listing instead of upper case first
|
||||||
- Key `-` to jump to last visited directory
|
- Key `-` to jump to last visited directory
|
||||||
|
@ -139,6 +140,7 @@ Start nnn (default: current directory):
|
||||||
| `D` | Show details of selected file |
|
| `D` | Show details of selected file |
|
||||||
| `.` | Toggle hide .dot files |
|
| `.` | Toggle hide .dot files |
|
||||||
| `s` | Toggle sort by file size |
|
| `s` | Toggle sort by file size |
|
||||||
|
| `S` | Toggle disk usage analyzer mode |
|
||||||
| `t` | Toggle sort by modified time |
|
| `t` | Toggle sort by modified time |
|
||||||
| `!` | Spawn `SHELL` in `PWD` (fallback sh) |
|
| `!` | Spawn `SHELL` in `PWD` (fallback sh) |
|
||||||
| `z` | Run `top` |
|
| `z` | Run `top` |
|
||||||
|
|
|
@ -5,6 +5,7 @@
|
||||||
|
|
||||||
static int mtimeorder = 0; /* Set to 1 to sort by time modified */
|
static int mtimeorder = 0; /* Set to 1 to sort by time modified */
|
||||||
static int sizeorder = 0; /* Set to 1 to sort by file size */
|
static int sizeorder = 0; /* Set to 1 to sort by file size */
|
||||||
|
static int bsizeorder = 0; /* Set to 1 to sort by blocks used including content */
|
||||||
static int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */
|
static int idletimeout = 0; /* Screensaver timeout in seconds, 0 to disable */
|
||||||
static int showhidden = 0; /* Set to 1 to show hidden files by default */
|
static int showhidden = 0; /* Set to 1 to show hidden files by default */
|
||||||
static int showdetail = 0; /* Set to show additional file info */
|
static int showdetail = 0; /* Set to show additional file info */
|
||||||
|
@ -75,6 +76,8 @@ struct key bindings[] = {
|
||||||
{ 'D', SEL_STATS, "", "" },
|
{ 'D', SEL_STATS, "", "" },
|
||||||
/* Toggle sort by size */
|
/* Toggle sort by size */
|
||||||
{ 's', SEL_FSIZE, "", "" },
|
{ 's', SEL_FSIZE, "", "" },
|
||||||
|
/* Sort by total block size including dir contents */
|
||||||
|
{ 'S', SEL_BSIZE, "", "" },
|
||||||
/* Toggle sort by time */
|
/* Toggle sort by time */
|
||||||
{ 't', SEL_MTIME, "", "" },
|
{ 't', SEL_MTIME, "", "" },
|
||||||
{ CONTROL('L'), SEL_REDRAW, "", "" },
|
{ CONTROL('L'), SEL_REDRAW, "", "" },
|
||||||
|
|
4
nnn.1
4
nnn.1
|
@ -10,7 +10,7 @@
|
||||||
.Op Ar dir
|
.Op Ar dir
|
||||||
.Sh DESCRIPTION
|
.Sh DESCRIPTION
|
||||||
.Nm
|
.Nm
|
||||||
(Noice is Not Noice) is a fork of the noice terminal file browser with improved desktop integration, file associations and navigation. It remains a simple and efficient file browser that stays out of your way.
|
(Noice is Not Noice) is a fork of the noice terminal file browser with improved desktop integration, file associations, navigation and disk usage analyzer mode. It remains a simple and efficient file browser that stays out of your way.
|
||||||
.Pp
|
.Pp
|
||||||
.Nm
|
.Nm
|
||||||
defaults to the current directory if
|
defaults to the current directory if
|
||||||
|
@ -54,6 +54,8 @@ Show details of selected file
|
||||||
Toggle hide .dot files
|
Toggle hide .dot files
|
||||||
.It Ic s
|
.It Ic s
|
||||||
Toggle sort by file size
|
Toggle sort by file size
|
||||||
|
.It Ic S
|
||||||
|
Toggle disk usage analyzer mode
|
||||||
.It Ic t
|
.It Ic t
|
||||||
Toggle sort by time modified
|
Toggle sort by time modified
|
||||||
.It Ic \&!
|
.It Ic \&!
|
||||||
|
|
110
nnn.c
110
nnn.c
|
@ -20,6 +20,9 @@
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
|
||||||
|
#define __USE_XOPEN_EXTENDED
|
||||||
|
#include <ftw.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
static int
|
static int
|
||||||
xprintf(int fd, const char *fmt, ...)
|
xprintf(int fd, const char *fmt, ...)
|
||||||
|
@ -82,6 +85,7 @@ enum action {
|
||||||
SEL_DETAIL,
|
SEL_DETAIL,
|
||||||
SEL_STATS,
|
SEL_STATS,
|
||||||
SEL_FSIZE,
|
SEL_FSIZE,
|
||||||
|
SEL_BSIZE,
|
||||||
SEL_MTIME,
|
SEL_MTIME,
|
||||||
SEL_REDRAW,
|
SEL_REDRAW,
|
||||||
SEL_COPY,
|
SEL_COPY,
|
||||||
|
@ -104,6 +108,7 @@ typedef struct entry {
|
||||||
mode_t mode;
|
mode_t mode;
|
||||||
time_t t;
|
time_t t;
|
||||||
off_t size;
|
off_t size;
|
||||||
|
off_t bsize;
|
||||||
} *pEntry;
|
} *pEntry;
|
||||||
|
|
||||||
typedef unsigned long ulong;
|
typedef unsigned long ulong;
|
||||||
|
@ -422,9 +427,19 @@ entrycmp(const void *va, const void *vb)
|
||||||
if (mtimeorder)
|
if (mtimeorder)
|
||||||
return pb->t - pa->t;
|
return pb->t - pa->t;
|
||||||
|
|
||||||
if (sizeorder)
|
if (sizeorder) {
|
||||||
if (pb->size != pa->size)
|
if (pb->size > pa->size)
|
||||||
return pb->size - pa->size;
|
return 1;
|
||||||
|
else if (pb->size < pa->size)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bsizeorder) {
|
||||||
|
if (pb->bsize > pa->bsize)
|
||||||
|
return 1;
|
||||||
|
else if (pb->bsize < pa->bsize)
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
return xstricmp(pa->name, pb->name);
|
return xstricmp(pa->name, pb->name);
|
||||||
}
|
}
|
||||||
|
@ -582,20 +597,25 @@ printent(struct entry *ent, int active)
|
||||||
}
|
}
|
||||||
|
|
||||||
static void (*printptr)(struct entry *ent, int active) = &printent;
|
static void (*printptr)(struct entry *ent, int active) = &printent;
|
||||||
|
static const double div_2_pow_10 = 1.0 / 1024.0;
|
||||||
|
|
||||||
static char*
|
static char*
|
||||||
coolsize(off_t size)
|
coolsize(off_t size)
|
||||||
{
|
{
|
||||||
static char size_buf[12]; /* Buffer to hold human readable size */
|
static char size_buf[12]; /* Buffer to hold human readable size */
|
||||||
int i = 0;
|
int i = 0;
|
||||||
long double fsize = (double)size;
|
off_t fsize = size, tmp;
|
||||||
|
long double rem = 0;
|
||||||
|
|
||||||
while (fsize > 1024) {
|
while (fsize > 1024) {
|
||||||
fsize /= 1024;
|
tmp = fsize;
|
||||||
|
//fsize *= div_2_pow_10;
|
||||||
|
fsize >>= 10;
|
||||||
|
rem = tmp - (fsize << 10);
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
|
|
||||||
snprintf(size_buf, 12, "%.*Lf%s", i, fsize, size_units[i]);
|
snprintf(size_buf, 12, "%.*Lf%s", i, fsize + rem * div_2_pow_10, size_units[i]);
|
||||||
return size_buf;
|
return size_buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,6 +628,7 @@ printent_long(struct entry *ent, int active)
|
||||||
if (active)
|
if (active)
|
||||||
attron(A_REVERSE);
|
attron(A_REVERSE);
|
||||||
|
|
||||||
|
if (!bsizeorder) {
|
||||||
if (S_ISDIR(ent->mode))
|
if (S_ISDIR(ent->mode))
|
||||||
printw("%s%-17.17s / %s/\n",
|
printw("%s%-17.17s / %s/\n",
|
||||||
CURSYM(active), buf, ent->name);
|
CURSYM(active), buf, ent->name);
|
||||||
|
@ -632,6 +653,32 @@ printent_long(struct entry *ent, int active)
|
||||||
else
|
else
|
||||||
printw("%s%-17.17s %8.8s %s\n", CURSYM(active),
|
printw("%s%-17.17s %8.8s %s\n", CURSYM(active),
|
||||||
buf, coolsize(ent->size), ent->name);
|
buf, coolsize(ent->size), ent->name);
|
||||||
|
} else {
|
||||||
|
if (S_ISDIR(ent->mode))
|
||||||
|
printw("%s%-17.17s %8.8s/ %s/\n", CURSYM(active),
|
||||||
|
buf, coolsize(ent->bsize << 9), ent->name);
|
||||||
|
else if (S_ISLNK(ent->mode))
|
||||||
|
printw("%s%-17.17s @ %s@\n",
|
||||||
|
CURSYM(active), buf, ent->name);
|
||||||
|
else if (S_ISSOCK(ent->mode))
|
||||||
|
printw("%s%-17.17s = %s=\n",
|
||||||
|
CURSYM(active), buf, ent->name);
|
||||||
|
else if (S_ISFIFO(ent->mode))
|
||||||
|
printw("%s%-17.17s | %s|\n",
|
||||||
|
CURSYM(active), buf, ent->name);
|
||||||
|
else if (S_ISBLK(ent->mode))
|
||||||
|
printw("%s%-17.17s b %s\n",
|
||||||
|
CURSYM(active), buf, ent->name);
|
||||||
|
else if (S_ISCHR(ent->mode))
|
||||||
|
printw("%s%-17.17s c %s\n",
|
||||||
|
CURSYM(active), buf, ent->name);
|
||||||
|
else if (ent->mode & S_IXUSR)
|
||||||
|
printw("%s%-17.17s %8.8s* %s*\n", CURSYM(active),
|
||||||
|
buf, coolsize(ent->bsize << 9), ent->name);
|
||||||
|
else
|
||||||
|
printw("%s%-17.17s %8.8s %s\n", CURSYM(active),
|
||||||
|
buf, coolsize(ent->bsize << 9), ent->name);
|
||||||
|
}
|
||||||
|
|
||||||
if (active)
|
if (active)
|
||||||
attroff(A_REVERSE);
|
attroff(A_REVERSE);
|
||||||
|
@ -862,6 +909,7 @@ show_help(void)
|
||||||
D Show details of selected file\n\
|
D Show details of selected file\n\
|
||||||
. Toggle hide .dot files\n\
|
. Toggle hide .dot files\n\
|
||||||
s Toggle sort by file size\n\
|
s Toggle sort by file size\n\
|
||||||
|
S Toggle disk usage analyzer mode\n\
|
||||||
t Toggle sort by modified time\n\
|
t Toggle sort by modified time\n\
|
||||||
! Spawn SHELL in PWD (fallback sh)\n\
|
! Spawn SHELL in PWD (fallback sh)\n\
|
||||||
z Run top\n\
|
z Run top\n\
|
||||||
|
@ -880,11 +928,30 @@ show_help(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
off_t blk_size;
|
||||||
|
|
||||||
|
static int
|
||||||
|
sum_sizes(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf)
|
||||||
|
{
|
||||||
|
if (!fpath || !ftwbuf)
|
||||||
|
printmsg("fpath or ftwbuf NULL"); /* TODO: on %s", fpath); */
|
||||||
|
|
||||||
|
/* Handle permission problems */
|
||||||
|
if(typeflag == FTW_NS) {
|
||||||
|
printmsg("No stats (permissions ?)"); /* TODO: on %s", fpath); */
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
blk_size += sb->st_blocks;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int
|
static int
|
||||||
dentfill(char *path, struct entry **dents,
|
dentfill(char *path, struct entry **dents,
|
||||||
int (*filter)(regex_t *, char *), regex_t *re)
|
int (*filter)(regex_t *, char *), regex_t *re)
|
||||||
{
|
{
|
||||||
char newpath[PATH_MAX];
|
static char newpath[PATH_MAX];
|
||||||
DIR *dirp;
|
DIR *dirp;
|
||||||
struct dirent *dp;
|
struct dirent *dp;
|
||||||
struct stat sb;
|
struct stat sb;
|
||||||
|
@ -911,6 +978,19 @@ dentfill(char *path, struct entry **dents,
|
||||||
(*dents)[n].mode = sb.st_mode;
|
(*dents)[n].mode = sb.st_mode;
|
||||||
(*dents)[n].t = sb.st_mtime;
|
(*dents)[n].t = sb.st_mtime;
|
||||||
(*dents)[n].size = sb.st_size;
|
(*dents)[n].size = sb.st_size;
|
||||||
|
|
||||||
|
if (bsizeorder) {
|
||||||
|
if (S_ISDIR(sb.st_mode)) {
|
||||||
|
blk_size = 0;
|
||||||
|
if (nftw(newpath, sum_sizes, 128, FTW_MOUNT | FTW_PHYS) == -1) {
|
||||||
|
printmsg("nftw(3) failed"); /* TODO: , newpath); */
|
||||||
|
(*dents)[n].bsize = sb.st_blocks;
|
||||||
|
} else
|
||||||
|
(*dents)[n].bsize = blk_size;
|
||||||
|
} else
|
||||||
|
(*dents)[n].bsize = sb.st_blocks;
|
||||||
|
}
|
||||||
|
|
||||||
n++;
|
n++;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1028,12 +1108,14 @@ redraw(char *path)
|
||||||
if (showdetail) {
|
if (showdetail) {
|
||||||
if (ndents) {
|
if (ndents) {
|
||||||
static char ind[2] = "\0\0";
|
static char ind[2] = "\0\0";
|
||||||
static char sort[9];
|
static char sort[17];
|
||||||
|
|
||||||
if (mtimeorder)
|
if (mtimeorder)
|
||||||
sprintf(sort, "by time ");
|
sprintf(sort, "by time ");
|
||||||
else if (sizeorder)
|
else if (sizeorder)
|
||||||
sprintf(sort, "by size ");
|
sprintf(sort, "by size ");
|
||||||
|
else if (bsizeorder)
|
||||||
|
sprintf(sort, "by content size ");
|
||||||
else
|
else
|
||||||
sort[0] = '\0';
|
sort[0] = '\0';
|
||||||
|
|
||||||
|
@ -1345,6 +1427,15 @@ nochange:
|
||||||
case SEL_FSIZE:
|
case SEL_FSIZE:
|
||||||
sizeorder = !sizeorder;
|
sizeorder = !sizeorder;
|
||||||
mtimeorder = 0;
|
mtimeorder = 0;
|
||||||
|
bsizeorder = 0;
|
||||||
|
/* Save current */
|
||||||
|
if (ndents > 0)
|
||||||
|
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||||
|
goto begin;
|
||||||
|
case SEL_BSIZE:
|
||||||
|
bsizeorder = !bsizeorder;
|
||||||
|
mtimeorder = 0;
|
||||||
|
sizeorder = 0;
|
||||||
/* Save current */
|
/* Save current */
|
||||||
if (ndents > 0)
|
if (ndents > 0)
|
||||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||||
|
@ -1352,6 +1443,7 @@ nochange:
|
||||||
case SEL_MTIME:
|
case SEL_MTIME:
|
||||||
mtimeorder = !mtimeorder;
|
mtimeorder = !mtimeorder;
|
||||||
sizeorder = 0;
|
sizeorder = 0;
|
||||||
|
bsizeorder = 0;
|
||||||
/* Save current */
|
/* Save current */
|
||||||
if (ndents > 0)
|
if (ndents > 0)
|
||||||
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
mkpath(path, dents[cur].name, oldpath, sizeof(oldpath));
|
||||||
|
@ -1387,7 +1479,7 @@ nochange:
|
||||||
exitcurses();
|
exitcurses();
|
||||||
spawn(run, NULL, path, 1);
|
spawn(run, NULL, path, 1);
|
||||||
initcurses();
|
initcurses();
|
||||||
/* Re-populate as directory content may have changed */
|
/* Repopulate as directory content may have changed */
|
||||||
goto begin;
|
goto begin;
|
||||||
case SEL_RUNARG:
|
case SEL_RUNARG:
|
||||||
run = xgetenv(env, run);
|
run = xgetenv(env, run);
|
||||||
|
|
Loading…
Reference in a new issue