nnn

mirror of https://github.com/jarun/nnn
Log | Files | Refs | README | LICENSE

mainline.diff (10609B)


      1 ]633;E;head -4 patches/namefirst/mainline.diff;15aca83b-a88c-4d34-bac5-a786145f3816]633;C# Description: Prints filenames first in the detail view.  Prints user/group
      2 #              columns when a directory contains different users/groups.
      3 #
      4 # Author: Luuk van Baal
      5 
      6 diff --git a/src/nnn.c b/src/nnn.c
      7 --- a/src/nnn.c
      8 +++ b/src/nnn.c
      9 @@ -432,6 +432,10 @@ typedef struct {
     10  } session_header_t;
     11  #endif
     12  
     13 +static struct {
     14 +	ushort_t maxnameln, maxsizeln, maxuidln, maxgidln, maxentln, uidln, gidln, printguid;
     15 +} dtls;
     16 +
     17  /* GLOBALS */
     18  
     19  /* Configuration, contexts */
     20 @@ -1177,10 +1181,13 @@ static char *getpwname(uid_t uid)
     21  	static char *namecache;
     22  
     23  	if (uidcache != uid) {
     24 +		if (dtls.maxuidln && !dtls.printguid)
     25 +			dtls.printguid = 1;
     26  		struct passwd *pw = getpwuid(uid);
     27  
     28  		uidcache = uid;
     29  		namecache = pw ? pw->pw_name : NULL;
     30 +		dtls.uidln = xstrlen(namecache ? namecache : xitoa(uid));
     31  	}
     32  
     33  	return namecache ? namecache : xitoa(uid);
     34 @@ -1192,10 +1199,13 @@ static char *getgrname(gid_t gid)
     35  	static char *grpcache;
     36  
     37  	if (gidcache != gid) {
     38 +		if (dtls.maxgidln && !dtls.printguid)
     39 +			dtls.printguid = 1;
     40  		struct group *gr = getgrgid(gid);
     41  
     42  		gidcache = gid;
     43  		grpcache = gr ? gr->gr_name : NULL;
     44 +		dtls.gidln = xstrlen(grpcache ? grpcache : xitoa(gid));
     45  	}
     46  
     47  	return grpcache ? grpcache : xitoa(gid);
     48 @@ -4572,14 +4582,13 @@ static void resetdircolor(int flags)
     49   * Max supported str length: NAME_MAX;
     50   */
     51  #ifdef NOLC
     52 -static char *unescape(const char *str, uint_t maxcols)
     53 +static size_t unescape(const char *str, uint_t maxcols)
     54  {
     55  	char * const wbuf = g_buf;
     56  	char *buf = wbuf;
     57 -
     58 -	xstrsncpy(wbuf, str, maxcols);
     59 +	size_t len = xstrsncpy(wbuf, str, maxcols);
     60  #else
     61 -static wchar_t *unescape(const char *str, uint_t maxcols)
     62 +static size_t unescape(const char *str, uint_t maxcols)
     63  {
     64  	wchar_t * const wbuf = (wchar_t *)g_buf;
     65  	wchar_t *buf = wbuf;
     66 @@ -4604,7 +4613,7 @@ static wchar_t *unescape(const char *str, uint_t maxcols)
     67  		++buf;
     68  	}
     69  
     70 -	return wbuf;
     71 +	return len;
     72  }
     73  
     74  static off_t get_size(off_t size, off_t *pval, int comp)
     75 @@ -4853,9 +4862,10 @@ static uchar_t get_color_pair_name_ind(const struct entry *ent, char *pind, int
     76  }
     77  
     78  #ifdef DIM_FILTERED
     79 -static void printent_name(const struct entry *ent, uint_t namecols)
     80 +static size_t printent_name(const struct entry *ent, uint_t namecols)
     81  {
     82  	char * const fltr = g_ctx[cfg.curctx].c_fltr;
     83 +	size_t namelen;
     84  
     85  	/* If there's a filter string, dim matching characters */
     86  	if (fltr[1]) {
     87 @@ -4866,15 +4876,18 @@ static void printent_name(const struct entry *ent, uint_t namecols)
     88  		if (cfg.regex) {
     89  			/* For regex, we don't dim - just print normally */
     90  #ifndef NOLC
     91 -			addwstr(unescape(ent->name, namecols));
     92 +			namelen = unescape(ent->name, namecols);
     93 +			addwstr((wchar_t *)g_buf);
     94  #else
     95 -			addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1));
     96 +			namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
     97 +			addstr((char *)g_buf);
     98  #endif
     99  		} else if (cfg.fuzzy) {
    100  			/* Get fuzzy match positions */
    101  			fuzzy_match_positions(fltr + 1, ent->name, matched);
    102  #ifndef NOLC
    103 -			wchar_t * const wbuf = unescape(ent->name, namecols);
    104 +			namelen = unescape(ent->name, namecols);
    105 +			wchar_t * const wbuf = (wchar_t *)g_buf;
    106  			uint_t col = 0;
    107  			for (wchar_t *p = wbuf; *p && col < namecols; ++p, ++col) {
    108  				if (matched[col]) {
    109 @@ -4887,7 +4900,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
    110  			}
    111  #else
    112  			/* Non-wide character version for fuzzy dimming */
    113 -			const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    114 +			namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    115 +			const char *name = (char *)g_buf;
    116  			for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
    117  				if (matched[i]) {
    118  					attron(match_attrs);
    119 @@ -4902,7 +4916,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
    120  			/* String match - dim the substring */
    121  			string_match_positions(fltr + 1, ent->name, matched);
    122  #ifndef NOLC
    123 -			wchar_t * const wbuf = unescape(ent->name, namecols);
    124 +			namelen = unescape(ent->name, namecols);
    125 +			wchar_t * const wbuf = (wchar_t *)g_buf;
    126  			uint_t col = 0;
    127  			for (wchar_t *p = wbuf; *p && col < namecols; ++p, ++col) {
    128  				if (matched[col]) {
    129 @@ -4915,7 +4930,8 @@ static void printent_name(const struct entry *ent, uint_t namecols)
    130  			}
    131  #else
    132  			/* Non-wide character version for string dimming */
    133 -			const char *name = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    134 +			namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    135 +			const char *name = (char *)g_buf;
    136  			for (uint_t i = 0; (i < namecols) && name[i]; ++i) {
    137  				if (matched[i]) {
    138  					attron(match_attrs);
    139 @@ -4930,21 +4946,29 @@ static void printent_name(const struct entry *ent, uint_t namecols)
    140  	} else {
    141  		/* No filter or filter not active - print normally */
    142  #ifndef NOLC
    143 -		addwstr(unescape(ent->name, namecols));
    144 +		namelen = unescape(ent->name, namecols);
    145 +		addwstr((wchar_t *)g_buf);
    146  #else
    147 -		addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1));
    148 +		namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    149 +		addstr((char *)g_buf);
    150  #endif
    151  	}
    152 +
    153 +	return namelen;
    154  }
    155  #else
    156  /* Without dimming support, just print the name normally */
    157 -static inline void printent_name(const struct entry *ent, uint_t namecols)
    158 +static inline size_t printent_name(const struct entry *ent, uint_t namecols)
    159  {
    160  #ifndef NOLC
    161 -	addwstr(unescape(ent->name, namecols));
    162 +	size_t namelen = unescape(ent->name, namecols);
    163 +	addwstr((wchar_t *)g_buf);
    164  #else
    165 -	addstr(unescape(ent->name, MIN(namecols, ent->nlen) + 1));
    166 +	size_t namelen = unescape(ent->name, MIN(namecols, ent->nlen) + 1);
    167 +	addstr((char *)g_buf);
    168  #endif
    169 +
    170 +	return namelen;
    171  }
    172  #endif
    173  
    174 @@ -4952,38 +4976,14 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
    175  {
    176  	const struct entry *ent = &pdents[pdents_index];
    177  	char ind = '\0';
    178 -	int attrs;
    179 -
    180 -	if (cfg.showdetail) {
    181 -		int type = ent->mode & S_IFMT;
    182 -		char perms[6] = {' ', ' ', (char)('0' + ((ent->mode >> 6) & 7)),
    183 -				(char)('0' + ((ent->mode >> 3) & 7)),
    184 -				(char)('0' + (ent->mode & 7)), '\0'};
    185 -
    186 -		addch(' ');
    187 -		attrs = g_state.oldcolor ? (resetdircolor(ent->flags), A_DIM)
    188 -					 : (fcolors[C_MIS] ? COLOR_PAIR(C_MIS) : 0);
    189 -		if (attrs)
    190 -			attron(attrs);
    191 -
    192 -		/* Print details */
    193 -		print_time(&ent->sec, ent->flags);
    194 -
    195 -		printw("%s%9s ", perms, (type == S_IFREG || type == S_IFDIR)
    196 -			? coolsize(cfg.blkorder ? (blkcnt_t)ent->blocks << blk_shift : ent->size)
    197 -			: (type = (uchar_t)get_detail_ind(ent->mode), (char *)&type));
    198 -
    199 -		if (attrs)
    200 -			attroff(attrs);
    201 -	}
    202 +	int attrs = 0;
    203 +	size_t namelen;
    204  
    205  	if (g_state.showlines) {
    206  		ptrdiff_t rel_num = pdents_index - cur;
    207  		printw(rel_num == 0 ? "%4td" : "%+4td", rel_num);
    208  	}
    209  
    210 -	attrs = 0;
    211 -
    212  	uchar_t color_pair = get_color_pair_name_ind(ent, &ind, &attrs);
    213  
    214  	addch((ent->flags & FILE_SELECTED) ? '+' | A_REVERSE | A_BOLD : ' ');
    215 @@ -5007,12 +5007,44 @@ static void printent(int pdents_index, uint_t namecols, bool sel)
    216  	if (!ind)
    217  		++namecols;
    218  
    219 -	printent_name(ent, namecols);
    220 +	namelen = printent_name(ent, namecols);
    221  
    222 -	if (attrs)
    223 +	if (!sel && attrs)
    224  		attroff(attrs);
    225  	if (ind)
    226  		addch(ind);
    227 +	if (cfg.showdetail) {
    228 +		int type = ent->mode & S_IFMT;
    229 +		char perms[6] = {(char)('0' + ((ent->mode >> 6) & 7)),
    230 +				(char)('0' + ((ent->mode >> 3) & 7)),
    231 +				(char)('0' + (ent->mode & 7)), ' ', ' ', '\0'}, *size = NULL;
    232 +
    233 +		if (attrs)
    234 +			attron(attrs);
    235 +		if (!g_state.oldcolor && (type == S_IFDIR || (type == S_IFLNK && ent->flags & DIR_OR_DIRLNK)))
    236 +			attroff(A_BOLD);
    237 +		int sizelen;
    238 +		if (type == S_IFREG || type == S_IFDIR) {
    239 +			size = coolsize(cfg.blkorder ? ent->blocks << blk_shift : ent->size);
    240 +			sizelen = xstrlen(size);
    241 +		} else
    242 +			sizelen = 1;
    243 +		printw("%*c%*s%s%s",
    244 +			1 + MIN(namecols, dtls.maxnameln + (uint_t)(ind ? 0 : 1)) - (int)namelen, ' ',
    245 +			dtls.maxsizeln - sizelen, "", size ? size
    246 +			: (type = (uchar_t)get_detail_ind(ent->mode), (char *)&type), "  ");
    247 +#ifndef NOUG
    248 +		if (g_state.uidgid && dtls.printguid) {
    249 +			addstr(getpwname(ent->uid));
    250 +			printw("%*c%s", dtls.maxuidln + 1 - dtls.uidln, ' ', getgrname(ent->gid));
    251 +			printw("%*c", dtls.maxgidln + 2 - dtls.gidln, ' ');
    252 +		}
    253 +#endif
    254 +		addstr(perms);
    255 +		print_time(&ent->sec, ent->flags);
    256 +	}
    257 +	if (attrs)
    258 +		attroff(attrs);
    259  }
    260  
    261  /**
    262 @@ -8063,10 +8063,2 @@ static void statusbar(char *path)
    263 -static inline void markhovered(void)
    264 -{
    265 -	if (cfg.showdetail && ndents) { /* Bold forward arrowhead */
    266 -		tocursor();
    267 -		addch('>' | A_BOLD);
    268 -	}
    269 -}
    270 -
    271  #define PREVIEW_BORDER_COL (xcols / 2)
    272  #define PREVIEW_COL        (PREVIEW_BORDER_COL + 2)
    273 @@ -8340,12 +8331,13 @@ static void preview_pane(const char *path)
    274  #ifdef ICONS_ENABLED
    275  	n -= (g_state.oldcolor ? 0 : ICON_SIZE + ICON_PADDING_LEFT_LEN + ICON_PADDING_RIGHT_LEN);
    276  #endif
    277 +
    278  	if (cfg.showdetail) {
    279  		/* Fallback to light mode if less than 35 columns */
    280 -		if (n < 36)
    281 +		if (n < (dtls.maxentln + 1 - dtls.maxnameln))
    282  			cfg.showdetail ^= 1;
    283  		else /* 2 more accounted for below */
    284 -			n -= 32;
    285 +			n -= (dtls.maxentln - 2 - dtls.maxnameln);
    286  	}
    287  
    288  	/* 2 columns for preceding space and indicator */
    289 @@ -8385,8 +8378,6 @@ static void draw_line(int ncols)
    290  	/* Must reset e.g. no files in dir */
    291  	if (dir)
    292  		attroff(COLOR_PAIR(cfg.curctx + 1) | A_BOLD);
    293 -
    294 -	markhovered();
    295  }
    296  
    297  static void redraw(char *path)
    298 @@ -8500,6 +8491,26 @@ static void redraw(char *path)
    299  	int onscreen = MIN(ONSCREEN + curscroll, ndents);
    300  	int len = scanselforpath(path, FALSE);
    301  
    302 +	if (cfg.showdetail) {
    303 +		ushort_t lenbuf = dtls.maxnameln = dtls.maxsizeln = dtls.maxuidln = dtls.maxgidln = dtls.printguid = 0;
    304 +		for (i = curscroll; i < onscreen; ++i) {
    305 +			if ((lenbuf = pdents[i].nlen - 1) > dtls.maxnameln)
    306 +				dtls.maxnameln = lenbuf;
    307 +			if ((lenbuf = xstrlen(coolsize(cfg.blkorder ? pdents[i].blocks << blk_shift : pdents[i].size))) > dtls.maxsizeln)
    308 +				dtls.maxsizeln = lenbuf;
    309 +#ifndef NOUG
    310 +			if (g_state.uidgid) {
    311 +				if ((getpwname(pdents[i].uid), dtls.uidln) > dtls.maxuidln)
    312 +					dtls.maxuidln = dtls.uidln;
    313 +				if ((getgrname(pdents[i].gid), dtls.gidln) > dtls.maxgidln)
    314 +					dtls.maxgidln = dtls.gidln;
    315 +			}
    316 +#endif
    317 +		}
    318 +		dtls.maxentln = dtls.maxnameln + dtls.maxsizeln
    319 +			+ (dtls.printguid ? (dtls.maxuidln + dtls.maxgidln + 29) : 26);
    320 +	}
    321 +
    322  	ncols = adjust_cols(ncols);
    323  
    324  	/* Print listing */
    325 @@ -8531,9 +8542,9 @@ static void redraw(char *path)
    326  	}
    327  
    328 -	markhovered();
    329 +	statusbar(path);
    330  
    331  	if (cfg.preview)
    332  		preview_pane(path);
    333  }
    334  
    335  static bool cdprep(char *lastdir, char *lastname, char *path, char *newpath)