mirror of
https://github.com/jarun/nnn.git
synced 2024-11-20 01:49:14 +00:00
Merge pull request #1436 from N-R-K/icon_compaction
icons: use a compact array
This commit is contained in:
commit
f829afe60b
|
@ -12,21 +12,23 @@
|
|||
|
||||
#ifdef ICONS_GENERATE
|
||||
|
||||
#define ICONS_PROBE_MAX_ALLOWED 6
|
||||
#define ICONS_MATCH_MAX ((size_t)-1)
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include "icons.h"
|
||||
|
||||
#ifdef NDEBUG
|
||||
#error "NDEBUG"
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include "icons.h"
|
||||
|
||||
#define ASSERT(X) assert(X)
|
||||
#define ARRLEN(X) (sizeof(X) / sizeof((X)[0]))
|
||||
#define MAX(A, B) ((A) > (B) ? (A) : (B))
|
||||
#define HGEN_ITERARATION (1ul << 14)
|
||||
#define ICONS_PROBE_MAX_ALLOWED 6
|
||||
#define ICONS_MATCH_MAX ((size_t)-1)
|
||||
|
||||
#if 0 /* enable for debugging */
|
||||
#define log(...) fprintf(stderr, "[INFO]: " __VA_ARGS__)
|
||||
#else
|
||||
|
@ -133,19 +135,9 @@ main(void)
|
|||
assert(found);
|
||||
}
|
||||
|
||||
log("hash_start: %u\n", (unsigned)hash_start);
|
||||
log("hash_mul : %u\n", (unsigned)hash_mul);
|
||||
log("max_probe : %u\n", max_probe);
|
||||
|
||||
printf("#ifndef INCLUDE_ICONS_GENERATED\n");
|
||||
printf("#define INCLUDE_ICONS_GENERATED\n\n");
|
||||
|
||||
printf("/*\n * NOTE: This file is automatically generated.\n");
|
||||
printf(" * DO NOT EDIT THIS FILE DIRECTLY.\n");
|
||||
printf(" * Use `icons.h` to customize icons\n */\n\n");
|
||||
|
||||
printf("#define hash_start %uu\n", hash_start);
|
||||
printf("#define hash_mul %uu\n\n", hash_mul);
|
||||
log("hash_start: %6u\n", (unsigned)hash_start);
|
||||
log("hash_mul : %6u\n", (unsigned)hash_mul);
|
||||
log("max_probe : %6u\n", max_probe);
|
||||
|
||||
size_t match_max = 0, icon_max = 0;
|
||||
for (size_t i = 0; i < ARRLEN(icons_name); ++i) {
|
||||
|
@ -160,18 +152,59 @@ main(void)
|
|||
icon_max = MAX(icon_max, strlen(exec_icon.icon) + 1);
|
||||
icon_max = MAX(icon_max, strlen(file_icon.icon) + 1);
|
||||
|
||||
const char *uniq[ARRLEN(icons_ext)] = {0};
|
||||
size_t uniq_head = 0;
|
||||
for (size_t i = 0; i < ARRLEN(icons_ext); ++i) {
|
||||
if (icons_ext[i].icon[0] == 0) continue;
|
||||
int isuniq = 1;
|
||||
for (size_t k = 0; k < uniq_head; ++k) {
|
||||
if (strcmp(uniq[k], icons_ext[i].icon) == 0) {
|
||||
isuniq = 0;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (isuniq) {
|
||||
assert(uniq_head < ARRLEN(uniq));
|
||||
uniq[uniq_head++] = icons_ext[i].icon;
|
||||
}
|
||||
}
|
||||
assert(uniq_head < (unsigned char)-1);
|
||||
|
||||
log("uniq icons: %6zu\n", uniq_head);
|
||||
log("no-compact: %6zu bytes\n", ARRLEN(table) * icon_max);
|
||||
log("compaction: %6zu bytes\n", uniq_head * icon_max + ARRLEN(table));
|
||||
|
||||
printf("#ifndef INCLUDE_ICONS_GENERATED\n");
|
||||
printf("#define INCLUDE_ICONS_GENERATED\n\n");
|
||||
|
||||
printf("/*\n * NOTE: This file is automatically generated.\n");
|
||||
printf(" * DO NOT EDIT THIS FILE DIRECTLY.\n");
|
||||
printf(" * Use `icons.h` to customize icons\n */\n\n");
|
||||
|
||||
printf("#define hash_start %uu\n", hash_start);
|
||||
printf("#define hash_mul %uu\n\n", hash_mul);
|
||||
printf("#define ICONS_PROBE_MAX %u\n", max_probe);
|
||||
printf("#define ICONS_MATCH_MAX %zuu\n\n", match_max);
|
||||
|
||||
printf("struct icon_pair { const char match[%zu]; const char icon[%zu]; unsigned char color; };\n\n",
|
||||
match_max, icon_max);
|
||||
|
||||
printf("static const struct icon_pair icons_ext[%zu] = {\n", ARRLEN(table));
|
||||
printf("static const char icons_ext_uniq[%zu][%zu] = {\n", uniq_head, icon_max);
|
||||
for (size_t i = 0; i < uniq_head; ++i)
|
||||
printf("\t\"%s\",\n", uniq[i]);
|
||||
printf("};\n\n");
|
||||
|
||||
printf("static const struct {\n\tconst char match[%zu];"
|
||||
"\n\tunsigned char idx;\n\tunsigned char color;\n} icons_ext[%zu] = {\n",
|
||||
match_max, ARRLEN(table));
|
||||
for (size_t i = 0; i < ARRLEN(table); ++i) {
|
||||
if (table[i].icon == NULL || table[i].icon[0] == '\0') /* skip empty entries */
|
||||
continue;
|
||||
printf("\t[%zu] = {\"%s\", \"%s\", %hhu },\n", i,
|
||||
table[i].match, table[i].icon, table[i].color);
|
||||
int k;
|
||||
for (k = 0; k < uniq_head; ++k) if (strcmp(table[i].icon, uniq[k]) == 0) break;
|
||||
assert(k < uniq_head);
|
||||
printf("\t[%3zu] = {\"%s\", %d, %hhu },\n",
|
||||
i, table[i].match, k, table[i].color);
|
||||
}
|
||||
printf("};\n\n");
|
||||
|
||||
|
@ -190,13 +223,13 @@ main(void)
|
|||
static uint16_t
|
||||
icon_ext_hash(const char *str)
|
||||
{
|
||||
const unsigned int z = 16 - ICONS_TABLE_SIZE; /* 16 == size of `hash` in bits */
|
||||
uint16_t hash = hash_start;
|
||||
for (size_t i = 0; i < ICONS_MATCH_MAX && str[i] != '\0'; ++i) {
|
||||
hash ^= TOUPPER((unsigned char)str[i]) + i;
|
||||
uint32_t i, hash = hash_start;
|
||||
const unsigned int z = (sizeof hash * CHAR_BIT) - ICONS_TABLE_SIZE;
|
||||
for (i = 0; i < ICONS_MATCH_MAX && str[i] != '\0'; ++i) {
|
||||
hash ^= TOUPPER((unsigned char)str[i]);
|
||||
hash *= hash_mul;
|
||||
}
|
||||
hash = (hash >> z) ^ hash;
|
||||
hash ^= (hash >> z);
|
||||
hash *= GOLDEN_RATIO_16;
|
||||
hash >>= z;
|
||||
ASSERT(hash < ARRLEN(table));
|
||||
|
|
|
@ -167,9 +167,11 @@ static const unsigned char init_colors[] = { COLOR_LIST };
|
|||
struct icon_pair { const char *match; const char *icon; unsigned char color; };
|
||||
#endif
|
||||
|
||||
static const struct icon_pair dir_icon = {"", ICON_DIRECTORY, 0};
|
||||
static const struct icon_pair file_icon = {"", ICON_FILE, 0};
|
||||
static const struct icon_pair exec_icon = {"", ICON_EXEC, 0};
|
||||
struct icon { const char *icon; unsigned char color; };
|
||||
|
||||
static const struct icon dir_icon = {ICON_DIRECTORY, 0};
|
||||
static const struct icon file_icon = {ICON_FILE, 0};
|
||||
static const struct icon exec_icon = {ICON_EXEC, 0};
|
||||
|
||||
static const struct icon_pair icons_name[] = {
|
||||
{".git", ICON_GIT, 0},
|
||||
|
|
30
src/nnn.c
30
src/nnn.c
|
@ -3961,16 +3961,14 @@ static char *get_lsperms(mode_t mode)
|
|||
}
|
||||
|
||||
#ifdef ICONS_ENABLED
|
||||
static const struct icon_pair *get_icon(const struct entry *ent)
|
||||
static struct icon get_icon(const struct entry *ent)
|
||||
{
|
||||
ushort_t i = 0;
|
||||
|
||||
for (; i < ELEMENTS(icons_name); ++i)
|
||||
for (size_t i = 0; i < ELEMENTS(icons_name); ++i)
|
||||
if (strcasecmp(ent->name, icons_name[i].match) == 0)
|
||||
return &icons_name[i];
|
||||
return (struct icon){ icons_name[i].icon, icons_name[i].color };
|
||||
|
||||
if (ent->flags & DIR_OR_DIRLNK)
|
||||
return &dir_icon;
|
||||
return dir_icon;
|
||||
|
||||
char *tmp = xextension(ent->name, ent->nlen);
|
||||
|
||||
|
@ -3979,29 +3977,27 @@ static const struct icon_pair *get_icon(const struct entry *ent)
|
|||
for (k = 0; k < ICONS_PROBE_MAX; ++k) {
|
||||
z = (h + k) % ELEMENTS(icons_ext);
|
||||
if (strcasecmp(tmp, icons_ext[z].match) == 0)
|
||||
return &icons_ext[z];
|
||||
return (struct icon){ icons_ext_uniq[icons_ext[z].idx], icons_ext[z].color };
|
||||
}
|
||||
}
|
||||
|
||||
/* If there's no match and the file is executable, icon that */
|
||||
if (ent->mode & 0100)
|
||||
return &exec_icon;
|
||||
|
||||
return &file_icon;
|
||||
return exec_icon;
|
||||
return file_icon;
|
||||
}
|
||||
|
||||
static void print_icon(const struct entry *ent, const int attrs)
|
||||
{
|
||||
const struct icon_pair *picon = get_icon(ent);
|
||||
|
||||
const struct icon icon = get_icon(ent);
|
||||
addstr(ICON_PADDING_LEFT);
|
||||
if (picon->color)
|
||||
attron(COLOR_PAIR(C_UND + 1 + picon->color));
|
||||
if (icon.color)
|
||||
attron(COLOR_PAIR(C_UND + 1 + icon.color));
|
||||
else if (attrs)
|
||||
attron(attrs);
|
||||
addstr(picon->icon);
|
||||
if (picon->color)
|
||||
attroff(COLOR_PAIR(C_UND + 1 + picon->color));
|
||||
addstr(icon.icon);
|
||||
if (icon.color)
|
||||
attroff(COLOR_PAIR(C_UND + 1 + icon.color));
|
||||
else if (attrs)
|
||||
attroff(attrs);
|
||||
addstr(ICON_PADDING_RIGHT);
|
||||
|
|
Loading…
Reference in a new issue