mirror of
https://github.com/jarun/nnn.git
synced 2024-11-24 11:51:27 +00:00
Utility functions to top, API to get file extn
This commit is contained in:
parent
a1b43ae830
commit
f712441eda
380
src/nnn.c
380
src/nnn.c
|
@ -732,15 +732,10 @@ static haiku_nm_h haiku_hnd;
|
|||
#endif /* __GNUC__ */
|
||||
|
||||
/* Forward declarations */
|
||||
static size_t xstrsncpy(char *restrict dst, const char *restrict src, size_t n);
|
||||
static void redraw(char *path);
|
||||
static int spawn(char *file, char *arg1, char *arg2, uchar flag);
|
||||
static int (*nftw_fn)(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf);
|
||||
static int dentfind(const char *fname, int n);
|
||||
static void move_cursor(int target, int ignore_scrolloff);
|
||||
static inline bool getutil(char *util);
|
||||
static size_t mkpath(const char *dir, const char *name, char *out);
|
||||
static bool plugscript(const char *plugin, uchar flags);
|
||||
static char *load_input(int fd, const char *path);
|
||||
static int set_sort_flags(int r);
|
||||
|
||||
|
@ -824,128 +819,6 @@ static bool test_clear_bit(uint nr)
|
|||
}
|
||||
#endif
|
||||
|
||||
static void clearinfoln(void)
|
||||
{
|
||||
move(xlines - 2, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
/* Clear the old prompt */
|
||||
static void clearoldprompt(void)
|
||||
{
|
||||
clearinfoln();
|
||||
tolastln();
|
||||
addch('\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Messages show up at the bottom */
|
||||
static inline void printmsg_nc(const char *msg)
|
||||
{
|
||||
tolastln();
|
||||
addstr(msg);
|
||||
addch('\n');
|
||||
}
|
||||
|
||||
static void printmsg(const char *msg)
|
||||
{
|
||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
||||
printmsg_nc(msg);
|
||||
attroff(COLOR_PAIR(cfg.curctx + 1));
|
||||
}
|
||||
|
||||
static void printwait(const char *msg, int *presel)
|
||||
{
|
||||
printmsg(msg);
|
||||
if (presel) {
|
||||
*presel = MSGWAIT;
|
||||
if (ndents)
|
||||
xstrsncpy(g_ctx[cfg.curctx].c_name, pdents[cur].name, NAME_MAX + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill curses and display error before exiting */
|
||||
static void printerr(int linenum)
|
||||
{
|
||||
exitcurses();
|
||||
perror(xitoa(linenum));
|
||||
if (!g_state.picker && selpath)
|
||||
unlink(selpath);
|
||||
free(pselbuf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static inline bool xconfirm(int c)
|
||||
{
|
||||
return (c == 'y' || c == 'Y');
|
||||
}
|
||||
|
||||
static int get_input(const char *prompt)
|
||||
{
|
||||
if (prompt)
|
||||
printmsg(prompt);
|
||||
cleartimeout();
|
||||
|
||||
int r = getch();
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
while (r == KEY_RESIZE) {
|
||||
if (prompt) {
|
||||
clearoldprompt();
|
||||
xlines = LINES;
|
||||
printmsg(prompt);
|
||||
}
|
||||
|
||||
r = getch();
|
||||
}
|
||||
#endif
|
||||
settimeout();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int get_cur_or_sel(void)
|
||||
{
|
||||
if (selbufpos && ndents) {
|
||||
if (cfg.prefersel)
|
||||
return 's';
|
||||
|
||||
int choice = get_input(messages[MSG_CUR_SEL_OPTS]);
|
||||
|
||||
return ((choice == 'c' || choice == 's') ? choice : 0);
|
||||
}
|
||||
|
||||
if (selbufpos)
|
||||
return 's';
|
||||
|
||||
if (ndents)
|
||||
return 'c';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xdelay(useconds_t delay)
|
||||
{
|
||||
refresh();
|
||||
usleep(delay);
|
||||
}
|
||||
|
||||
static char confirm_force(bool selection)
|
||||
{
|
||||
char str[64];
|
||||
|
||||
snprintf(str, 64, messages[MSG_FORCE_RM],
|
||||
(selection ? xitoa(nselected) : "current"), (selection ? "(s)" : ""));
|
||||
|
||||
int r = get_input(str);
|
||||
|
||||
if (r == 27)
|
||||
return '\0'; /* cancel */
|
||||
if (r == 'y' || r == 'Y')
|
||||
return 'f'; /* forceful */
|
||||
return 'i'; /* interactive */
|
||||
}
|
||||
|
||||
/* Increase the limit on open file descriptors, if possible */
|
||||
static rlim_t max_openfds(void)
|
||||
{
|
||||
|
@ -1071,6 +944,58 @@ static void *xmemrchr(uchar *restrict s, uchar ch, size_t n)
|
|||
#endif
|
||||
}
|
||||
|
||||
/* A very simplified implementation, changes path */
|
||||
static char *xdirname(char *path)
|
||||
{
|
||||
char *base = xmemrchr((uchar *)path, '/', xstrlen(path));
|
||||
|
||||
if (base == path)
|
||||
path[1] = '\0';
|
||||
else
|
||||
*base = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static char *xbasename(char *path)
|
||||
{
|
||||
char *base = xmemrchr((uchar *)path, '/', xstrlen(path)); // NOLINT
|
||||
|
||||
return base ? base + 1 : path;
|
||||
}
|
||||
|
||||
static char *xextension(const char *fname, size_t len)
|
||||
{
|
||||
return xmemrchr((uchar *)fname, '.', len);
|
||||
}
|
||||
|
||||
static inline bool getutil(char *util)
|
||||
{
|
||||
return spawn("which", util, NULL, F_NORMAL | F_NOTRACE) == 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Updates out with "dir/name or "/name"
|
||||
* Returns the number of bytes copied including the terminating NULL byte
|
||||
*/
|
||||
static size_t mkpath(const char *dir, const char *name, char *out)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* Handle absolute path */
|
||||
if (name[0] == '/') // NOLINT
|
||||
return xstrsncpy(out, name, PATH_MAX);
|
||||
|
||||
/* Handle root case */
|
||||
if (istopdir(dir))
|
||||
len = 1;
|
||||
else
|
||||
len = xstrsncpy(out, dir, PATH_MAX);
|
||||
|
||||
out[len - 1] = '/'; // NOLINT
|
||||
return (xstrsncpy(out + len, name, PATH_MAX - len) + len);
|
||||
}
|
||||
|
||||
/* Assumes both the paths passed are directories */
|
||||
static char *common_prefix(const char *path, char *prefix)
|
||||
{
|
||||
|
@ -1174,26 +1099,6 @@ static char *abspath(const char *path, const char *cwd)
|
|||
return resolved_path;
|
||||
}
|
||||
|
||||
/* A very simplified implementation, changes path */
|
||||
static char *xdirname(char *path)
|
||||
{
|
||||
char *base = xmemrchr((uchar *)path, '/', xstrlen(path));
|
||||
|
||||
if (base == path)
|
||||
path[1] = '\0';
|
||||
else
|
||||
*base = '\0';
|
||||
|
||||
return path;
|
||||
}
|
||||
|
||||
static char *xbasename(char *path)
|
||||
{
|
||||
char *base = xmemrchr((uchar *)path, '/', xstrlen(path)); // NOLINT
|
||||
|
||||
return base ? base + 1 : path;
|
||||
}
|
||||
|
||||
static int create_tmp_file(void)
|
||||
{
|
||||
xstrsncpy(g_tmpfpath + tmpfplen - 1, messages[STR_TMPFILE], TMP_LEN_MAX - tmpfplen);
|
||||
|
@ -1207,6 +1112,128 @@ static int create_tmp_file(void)
|
|||
return fd;
|
||||
}
|
||||
|
||||
static void clearinfoln(void)
|
||||
{
|
||||
move(xlines - 2, 0);
|
||||
clrtoeol();
|
||||
}
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
/* Clear the old prompt */
|
||||
static void clearoldprompt(void)
|
||||
{
|
||||
clearinfoln();
|
||||
tolastln();
|
||||
addch('\n');
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Messages show up at the bottom */
|
||||
static inline void printmsg_nc(const char *msg)
|
||||
{
|
||||
tolastln();
|
||||
addstr(msg);
|
||||
addch('\n');
|
||||
}
|
||||
|
||||
static void printmsg(const char *msg)
|
||||
{
|
||||
attron(COLOR_PAIR(cfg.curctx + 1));
|
||||
printmsg_nc(msg);
|
||||
attroff(COLOR_PAIR(cfg.curctx + 1));
|
||||
}
|
||||
|
||||
static void printwait(const char *msg, int *presel)
|
||||
{
|
||||
printmsg(msg);
|
||||
if (presel) {
|
||||
*presel = MSGWAIT;
|
||||
if (ndents)
|
||||
xstrsncpy(g_ctx[cfg.curctx].c_name, pdents[cur].name, NAME_MAX + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/* Kill curses and display error before exiting */
|
||||
static void printerr(int linenum)
|
||||
{
|
||||
exitcurses();
|
||||
perror(xitoa(linenum));
|
||||
if (!g_state.picker && selpath)
|
||||
unlink(selpath);
|
||||
free(pselbuf);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
static inline bool xconfirm(int c)
|
||||
{
|
||||
return (c == 'y' || c == 'Y');
|
||||
}
|
||||
|
||||
static int get_input(const char *prompt)
|
||||
{
|
||||
if (prompt)
|
||||
printmsg(prompt);
|
||||
cleartimeout();
|
||||
|
||||
int r = getch();
|
||||
|
||||
#ifdef KEY_RESIZE
|
||||
while (r == KEY_RESIZE) {
|
||||
if (prompt) {
|
||||
clearoldprompt();
|
||||
xlines = LINES;
|
||||
printmsg(prompt);
|
||||
}
|
||||
|
||||
r = getch();
|
||||
}
|
||||
#endif
|
||||
settimeout();
|
||||
return r;
|
||||
}
|
||||
|
||||
static int get_cur_or_sel(void)
|
||||
{
|
||||
if (selbufpos && ndents) {
|
||||
if (cfg.prefersel)
|
||||
return 's';
|
||||
|
||||
int choice = get_input(messages[MSG_CUR_SEL_OPTS]);
|
||||
|
||||
return ((choice == 'c' || choice == 's') ? choice : 0);
|
||||
}
|
||||
|
||||
if (selbufpos)
|
||||
return 's';
|
||||
|
||||
if (ndents)
|
||||
return 'c';
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void xdelay(useconds_t delay)
|
||||
{
|
||||
refresh();
|
||||
usleep(delay);
|
||||
}
|
||||
|
||||
static char confirm_force(bool selection)
|
||||
{
|
||||
char str[64];
|
||||
|
||||
snprintf(str, 64, messages[MSG_FORCE_RM],
|
||||
(selection ? xitoa(nselected) : "current"), (selection ? "(s)" : ""));
|
||||
|
||||
int r = get_input(str);
|
||||
|
||||
if (r == 27)
|
||||
return '\0'; /* cancel */
|
||||
if (r == 'y' || r == 'Y')
|
||||
return 'f'; /* forceful */
|
||||
return 'i'; /* interactive */
|
||||
}
|
||||
|
||||
/* Writes buflen char(s) from buf to a file */
|
||||
static void writesel(const char *buf, const size_t buflen)
|
||||
{
|
||||
|
@ -2395,8 +2422,8 @@ static int entrycmp(const void *va, const void *vb)
|
|||
if (pb->blocks < pa->blocks)
|
||||
return -1;
|
||||
} else if (cfg.extnorder && !(pb->flags & DIR_OR_LINK_TO_DIR)) {
|
||||
char *extna = xmemrchr((uchar *)pa->name, '.', pa->nlen - 1);
|
||||
char *extnb = xmemrchr((uchar *)pb->name, '.', pb->nlen - 1);
|
||||
char *extna = xextension(pa->name, pa->nlen - 1);
|
||||
char *extnb = xextension(pb->name, pb->nlen - 1);
|
||||
|
||||
if (extna || extnb) {
|
||||
if (!extna)
|
||||
|
@ -2650,6 +2677,19 @@ static int matches(const char *fltr)
|
|||
return ndents;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the position of the matching entry or 0 otherwise
|
||||
* Note there's no NULL check for fname
|
||||
*/
|
||||
static int dentfind(const char *fname, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (xstrcmp(fname, pdents[i].name) == 0)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int filterentries(char *path, char *lastname)
|
||||
{
|
||||
wchar_t *wln = (wchar_t *)alloca(sizeof(wchar_t) * REGEX_MAX);
|
||||
|
@ -3055,28 +3095,6 @@ static char *getreadline(const char *prompt)
|
|||
}
|
||||
#endif
|
||||
|
||||
/*
|
||||
* Updates out with "dir/name or "/name"
|
||||
* Returns the number of bytes copied including the terminating NULL byte
|
||||
*/
|
||||
static size_t mkpath(const char *dir, const char *name, char *out)
|
||||
{
|
||||
size_t len;
|
||||
|
||||
/* Handle absolute path */
|
||||
if (name[0] == '/') // NOLINT
|
||||
return xstrsncpy(out, name, PATH_MAX);
|
||||
|
||||
/* Handle root case */
|
||||
if (istopdir(dir))
|
||||
len = 1;
|
||||
else
|
||||
len = xstrsncpy(out, dir, PATH_MAX);
|
||||
|
||||
out[len - 1] = '/'; // NOLINT
|
||||
return (xstrsncpy(out + len, name, PATH_MAX - len) + len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Create symbolic/hard link(s) to file(s) in selection list
|
||||
* Returns the number of links created, -1 on error
|
||||
|
@ -3889,11 +3907,6 @@ static char *get_output(char *buf, const size_t bytes, const char *file,
|
|||
return NULL;
|
||||
}
|
||||
|
||||
static inline bool getutil(char *util)
|
||||
{
|
||||
return spawn("which", util, NULL, F_NORMAL | F_NOTRACE) == 0;
|
||||
}
|
||||
|
||||
static void pipetof(char *cmd, FILE *fout)
|
||||
{
|
||||
FILE *fin = popen(cmd, "r");
|
||||
|
@ -4977,19 +4990,6 @@ exit:
|
|||
return n;
|
||||
}
|
||||
|
||||
/*
|
||||
* Return the position of the matching entry or 0 otherwise
|
||||
* Note there's no NULL check for fname
|
||||
*/
|
||||
static int dentfind(const char *fname, int n)
|
||||
{
|
||||
for (int i = 0; i < n; ++i)
|
||||
if (xstrcmp(fname, pdents[i].name) == 0)
|
||||
return i;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void populate(char *path, char *lastname)
|
||||
{
|
||||
#ifdef DBGMODE
|
||||
|
@ -5346,7 +5346,7 @@ static void statusbar(char *path)
|
|||
/* Get the file extension for regular files */
|
||||
if (S_ISREG(pent->mode)) {
|
||||
i = (int)(pent->nlen - 1);
|
||||
ptr = xmemrchr((uchar *)pent->name, '.', i);
|
||||
ptr = xextension(pent->name, i);
|
||||
if (ptr)
|
||||
extnlen = i - (ptr - pent->name);
|
||||
if (!ptr || extnlen > 5 || extnlen < 2)
|
||||
|
|
Loading…
Reference in a new issue