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)