| | @@ -88,10 +88,12 @@ |
| 88 | 88 | #define LS_MTIME 0x004 /* -t Sort by mtime, newest first */ |
| 89 | 89 | #define LS_SIZE 0x008 /* -S Sort by size, largest first */ |
| 90 | 90 | #define LS_COMMA 0x010 /* -m Comma-separated list */ |
| 91 | 91 | #define LS_DIRONLY 0x020 /* -d Show just directory name, not content */ |
| 92 | 92 | #define LS_ALL 0x040 /* -a Show all entries */ |
| 93 | +#define LS_COLOR 0x080 /* Colorize the output */ |
| 94 | +#define LS_COLUMNS 0x100 /* -C Split column output */ |
| 93 | 95 | |
| 94 | 96 | /* xWrite() callback from QRF |
| 95 | 97 | */ |
| 96 | 98 | static int xsystem_write(void *NotUsed, const char *zText, sqlite3_int64 n){ |
| 97 | 99 | fossil_puts(zText, 0, (int)n); |
| | @@ -138,11 +140,11 @@ |
| 138 | 140 | for(i=0; i<nList; i++){ |
| 139 | 141 | char *zFile = zPrefix ? mprintf("%s/%s",zPrefix,azList[i]) : azList[i]; |
| 140 | 142 | int mode = file_mode(zFile, ExtFILE); |
| 141 | 143 | sqlite3_int64 sz = file_size(zFile, ExtFILE); |
| 142 | 144 | sqlite3_int64 mtime = file_mtime(zFile, ExtFILE); |
| 143 | | - sqlite3_bind_text(pStmt, 1, zFile, -1, SQLITE_TRANSIENT); |
| 145 | + sqlite3_bind_text(pStmt, 1, azList[i], -1, SQLITE_TRANSIENT); |
| 144 | 146 | sqlite3_bind_int64(pStmt, 2, mtime); |
| 145 | 147 | sqlite3_bind_int64(pStmt, 3, sz); |
| 146 | 148 | sqlite3_bind_int(pStmt, 4, mode); |
| 147 | 149 | sqlite3_bind_int64(pStmt, 5, strlen(zFile)); |
| 148 | 150 | /* TODO: wcwidth()------^^^^^^ */ |
| | @@ -173,11 +175,11 @@ |
| 173 | 175 | if( mFlags & LS_REVERSE ) i += 3; |
| 174 | 176 | return zSortTypes[i]; |
| 175 | 177 | } |
| 176 | 178 | |
| 177 | 179 | /* |
| 178 | | -** colorize_fn(fn,mode) |
| 180 | +** color(fn,mode) |
| 179 | 181 | ** |
| 180 | 182 | ** SQL function to colorize a filename based on its mode. |
| 181 | 183 | */ |
| 182 | 184 | static void colorNameFunc( |
| 183 | 185 | sqlite3_context *context, |
| | @@ -201,12 +203,22 @@ |
| 201 | 203 | } |
| 202 | 204 | sqlite3_str_appendall(pOut, zName); |
| 203 | 205 | if( (iMode & 040100)!=0 ){ |
| 204 | 206 | sqlite3_str_appendall(pOut, "\033[0m"); |
| 205 | 207 | } |
| 206 | | - sqlite3_result_text(context, sqlite3_str_finish(pOut), -1, sqlite3_free); |
| 208 | + sqlite3_result_text(context, sqlite3_str_value(pOut), -1, SQLITE_TRANSIENT); |
| 209 | + sqlite3_str_free(pOut); |
| 210 | +} |
| 211 | +/* Alternative implementation that does *not* introduce color */ |
| 212 | +static void nocolorNameFunc( |
| 213 | + sqlite3_context *context, |
| 214 | + int argc, |
| 215 | + sqlite3_value **argv |
| 216 | +){ |
| 217 | + sqlite3_result_value(context, argv[0]); |
| 207 | 218 | } |
| 219 | + |
| 208 | 220 | |
| 209 | 221 | |
| 210 | 222 | /* |
| 211 | 223 | ** Show ls output information for content in the LS table |
| 212 | 224 | */ |
| | @@ -213,11 +225,15 @@ |
| 213 | 225 | static void xsystem_ls_render( |
| 214 | 226 | sqlite3 *db, |
| 215 | 227 | int mFlags |
| 216 | 228 | ){ |
| 217 | 229 | sqlite3_stmt *pStmt; |
| 218 | | - sqlite3_create_function(db, "color", 2, SQLITE_UTF8, 0, colorNameFunc,0,0); |
| 230 | + if( mFlags & LS_COLOR ){ |
| 231 | + sqlite3_create_function(db, "color",2,SQLITE_UTF8,0,colorNameFunc,0,0); |
| 232 | + }else{ |
| 233 | + sqlite3_create_function(db, "color",2,SQLITE_UTF8,0,nocolorNameFunc,0,0); |
| 234 | + } |
| 219 | 235 | if( (mFlags & LS_LONG)!=0 ){ |
| 220 | 236 | /* Long mode */ |
| 221 | 237 | char *zSql; |
| 222 | 238 | int szSz = 8; |
| 223 | 239 | sqlite3_prepare_v2(db, "SELECT length(max(size)) FROM ls", -1, &pStmt, 0); |
| | @@ -295,14 +311,16 @@ |
| 295 | 311 | char *zSql; |
| 296 | 312 | memset(&spec, 0, sizeof(spec)); |
| 297 | 313 | spec.iVersion = 1; |
| 298 | 314 | spec.xWrite = xsystem_write; |
| 299 | 315 | spec.eStyle = QRF_STYLE_Column; |
| 300 | | - spec.bSplitColumn = QRF_Yes; |
| 301 | 316 | spec.bTitles = QRF_No; |
| 302 | 317 | spec.eEsc = QRF_No; |
| 303 | | - spec.nScreenWidth = terminal_get_width(80); |
| 318 | + if( mFlags & LS_COLUMNS ){ |
| 319 | + spec.nScreenWidth = terminal_get_width(80); |
| 320 | + spec.bSplitColumn = QRF_Yes; |
| 321 | + } |
| 304 | 322 | zSql = mprintf("SELECT color(fn,mode) FROM ls ORDER BY %s", |
| 305 | 323 | xsystem_ls_orderby(mFlags)); |
| 306 | 324 | sqlite3_prepare_v2(db, zSql, -1, &pStmt, 0); |
| 307 | 325 | fossil_free(zSql); |
| 308 | 326 | sqlite3_format_query_result(pStmt, &spec, 0); |
| | @@ -313,10 +331,12 @@ |
| 313 | 331 | |
| 314 | 332 | /* List files "ls" |
| 315 | 333 | ** Options: |
| 316 | 334 | ** |
| 317 | 335 | ** -a Show files that begin with "." |
| 336 | +** -C List by colums |
| 337 | +** --color=WHEN Colorize output? |
| 318 | 338 | ** -d Show just directory names, not content |
| 319 | 339 | ** -l Long listing |
| 320 | 340 | ** -m Comma-separated list |
| 321 | 341 | ** -r Reverse sort |
| 322 | 342 | ** -S Sort by size, largest first |
| | @@ -327,10 +347,11 @@ |
| 327 | 347 | sqlite3 *db; |
| 328 | 348 | sqlite3_stmt *pStmt = 0; |
| 329 | 349 | int mFlags = 0; |
| 330 | 350 | int nFile = 0; |
| 331 | 351 | int nDir = 0; |
| 352 | + int bAutoColor = 1; |
| 332 | 353 | int needBlankLine = 0; |
| 333 | 354 | rc = sqlite3_open(":memory:", &db); |
| 334 | 355 | if( rc || db==0 ){ |
| 335 | 356 | fossil_fatal("Cannot open in-memory database"); |
| 336 | 357 | } |
| | @@ -341,22 +362,35 @@ |
| 341 | 362 | fossil_fatal("Cannot prepare INSERT statement"); |
| 342 | 363 | } |
| 343 | 364 | for(i=1; i<argc; i++){ |
| 344 | 365 | const char *z = argv[i]; |
| 345 | 366 | if( z[0]=='-' ){ |
| 346 | | - int k; |
| 347 | | - for(k=1; z[k]; k++){ |
| 348 | | - switch( z[k] ){ |
| 349 | | - case 'a': mFlags |= LS_ALL; break; |
| 350 | | - case 'd': mFlags |= LS_DIRONLY; break; |
| 351 | | - case 'l': mFlags |= LS_LONG; break; |
| 352 | | - case 'm': mFlags |= LS_COMMA; break; |
| 353 | | - case 'r': mFlags |= LS_REVERSE; break; |
| 354 | | - case 'S': mFlags |= LS_SIZE; break; |
| 355 | | - case 't': mFlags |= LS_MTIME; break; |
| 356 | | - default: { |
| 357 | | - fossil_fatal("unknown option: -%c", z[k]); |
| 367 | + if( z[1]=='-' ){ |
| 368 | + if( strncmp(z,"--color",7)==0 ){ |
| 369 | + if( z[7]==0 || strcmp(&z[7],"=always")==0 ){ |
| 370 | + mFlags |= LS_COLOR; |
| 371 | + }else if( strcmp(&z[7],"=never")==0 ){ |
| 372 | + bAutoColor = 0; |
| 373 | + } |
| 374 | + }else{ |
| 375 | + fossil_fatal("unknown option: %s", z); |
| 376 | + } |
| 377 | + }else{ |
| 378 | + int k; |
| 379 | + for(k=1; z[k]; k++){ |
| 380 | + switch( z[k] ){ |
| 381 | + case 'a': mFlags |= LS_ALL; break; |
| 382 | + case 'd': mFlags |= LS_DIRONLY; break; |
| 383 | + case 'l': mFlags |= LS_LONG; break; |
| 384 | + case 'm': mFlags |= LS_COMMA; break; |
| 385 | + case 'r': mFlags |= LS_REVERSE; break; |
| 386 | + case 'S': mFlags |= LS_SIZE; break; |
| 387 | + case 't': mFlags |= LS_MTIME; break; |
| 388 | + case 'C': mFlags |= LS_COLUMNS; break; |
| 389 | + default: { |
| 390 | + fossil_fatal("unknown option: -%c", z[k]); |
| 391 | + } |
| 358 | 392 | } |
| 359 | 393 | } |
| 360 | 394 | } |
| 361 | 395 | }else{ |
| 362 | 396 | if( (mFlags & LS_DIRONLY)==0 && file_isdir(z, ExtFILE)==1 ){ |
| | @@ -364,10 +398,14 @@ |
| 364 | 398 | }else{ |
| 365 | 399 | nFile++; |
| 366 | 400 | xsystem_ls_insert(pStmt, z, mFlags); |
| 367 | 401 | } |
| 368 | 402 | } |
| 403 | + } |
| 404 | + if( fossil_isatty(1) ){ |
| 405 | + if( bAutoColor ) mFlags |= LS_COLOR; |
| 406 | + mFlags |= LS_COLUMNS; |
| 369 | 407 | } |
| 370 | 408 | if( nFile>0 ){ |
| 371 | 409 | xsystem_ls_render(db, mFlags); |
| 372 | 410 | needBlankLine = 1; |
| 373 | 411 | }else if( nDir==0 ){ |
| | @@ -407,16 +445,18 @@ |
| 407 | 445 | }, |
| 408 | 446 | { "ls", xsystem_ls, |
| 409 | 447 | "[OPTIONS] [PATH] ...\n" |
| 410 | 448 | "Options:\n" |
| 411 | 449 | " -a Show files that begin with '.'\n" |
| 450 | + " -C Split columns\n" |
| 412 | 451 | " -d Show just directory names, not content\n" |
| 413 | 452 | " -l Long listing\n" |
| 414 | 453 | " -m Comma-separated list\n" |
| 415 | 454 | " -r Reverse sort order\n" |
| 416 | 455 | " -S Sort by size, largest first\n" |
| 417 | 456 | " -t Sort by mtime, newest first\n" |
| 457 | + " --color[=WHEN] Colorize output?\n" |
| 418 | 458 | }, |
| 419 | 459 | { "pwd", xsystem_pwd, |
| 420 | 460 | "\n" |
| 421 | 461 | "Show the Present Working Directory name\n" |
| 422 | 462 | }, |
| 423 | 463 | |