shfs 0.3.2 → 0.3.3

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -1861,6 +1861,143 @@ function compileTouch(cmd) {
1861
1861
  }
1862
1862
  };
1863
1863
  }
1864
+ const DEFAULT_TOTAL_MODE = "auto";
1865
+ function compileWc(command) {
1866
+ return {
1867
+ cmd: "wc",
1868
+ args: parseWcArgs(command.args)
1869
+ };
1870
+ }
1871
+ function parseWcArgs(argv) {
1872
+ const args = {
1873
+ bytes: false,
1874
+ chars: false,
1875
+ files: [],
1876
+ files0From: null,
1877
+ lines: false,
1878
+ maxLineLength: false,
1879
+ total: DEFAULT_TOTAL_MODE,
1880
+ words: false
1881
+ };
1882
+ for (let index = 0; index < argv.length; index++) {
1883
+ const word = argv[index];
1884
+ if (!word) continue;
1885
+ const token = expandedWordToString(word);
1886
+ if (token === "--") {
1887
+ args.files.push(...argv.slice(index + 1));
1888
+ break;
1889
+ }
1890
+ if (!token.startsWith("-") || token === "-") {
1891
+ args.files.push(word);
1892
+ continue;
1893
+ }
1894
+ const parsed = parseLongOption(argv, index, token, args);
1895
+ if (parsed.matched) {
1896
+ index = parsed.nextIndex - 1;
1897
+ continue;
1898
+ }
1899
+ parseShortOptions(token, args);
1900
+ }
1901
+ return args;
1902
+ }
1903
+ function parseLongOption(argv, index, token, args) {
1904
+ if (token === "--bytes") {
1905
+ args.bytes = true;
1906
+ return {
1907
+ matched: true,
1908
+ nextIndex: index + 1
1909
+ };
1910
+ }
1911
+ if (token === "--chars") {
1912
+ args.chars = true;
1913
+ return {
1914
+ matched: true,
1915
+ nextIndex: index + 1
1916
+ };
1917
+ }
1918
+ if (token === "--lines") {
1919
+ args.lines = true;
1920
+ return {
1921
+ matched: true,
1922
+ nextIndex: index + 1
1923
+ };
1924
+ }
1925
+ if (token === "--words") {
1926
+ args.words = true;
1927
+ return {
1928
+ matched: true,
1929
+ nextIndex: index + 1
1930
+ };
1931
+ }
1932
+ if (token === "--max-line-length") {
1933
+ args.maxLineLength = true;
1934
+ return {
1935
+ matched: true,
1936
+ nextIndex: index + 1
1937
+ };
1938
+ }
1939
+ if (token.startsWith("--files0-from=")) {
1940
+ args.files0From = {
1941
+ kind: "literal",
1942
+ value: token.slice(14)
1943
+ };
1944
+ return {
1945
+ matched: true,
1946
+ nextIndex: index + 1
1947
+ };
1948
+ }
1949
+ if (token === "--files0-from") {
1950
+ const value = argv[index + 1];
1951
+ if (!value) throw new Error("wc: option --files0-from requires an argument");
1952
+ args.files0From = value;
1953
+ return {
1954
+ matched: true,
1955
+ nextIndex: index + 2
1956
+ };
1957
+ }
1958
+ if (token.startsWith("--total=")) {
1959
+ args.total = parseTotalMode(token.slice(8));
1960
+ return {
1961
+ matched: true,
1962
+ nextIndex: index + 1
1963
+ };
1964
+ }
1965
+ if (token === "--total") {
1966
+ args.total = "invalid";
1967
+ return {
1968
+ matched: true,
1969
+ nextIndex: index + 1
1970
+ };
1971
+ }
1972
+ return {
1973
+ matched: false,
1974
+ nextIndex: index
1975
+ };
1976
+ }
1977
+ function parseShortOptions(token, args) {
1978
+ for (const option of token.slice(1)) switch (option) {
1979
+ case "c":
1980
+ args.bytes = true;
1981
+ break;
1982
+ case "m":
1983
+ args.chars = true;
1984
+ break;
1985
+ case "l":
1986
+ args.lines = true;
1987
+ break;
1988
+ case "w":
1989
+ args.words = true;
1990
+ break;
1991
+ case "L":
1992
+ args.maxLineLength = true;
1993
+ break;
1994
+ default: throw new Error(`wc: unknown option -- ${option}`);
1995
+ }
1996
+ }
1997
+ function parseTotalMode(value) {
1998
+ if (value === "auto" || value === "always" || value === "never" || value === "only") return value;
1999
+ throw new Error(`wc: invalid --total value: ${value}`);
2000
+ }
1864
2001
  const DEFAULT_COMMAND = [literal("echo")];
1865
2002
  const NUL_DELIMITER = "\0";
1866
2003
  function compileXargs(command) {
@@ -2015,6 +2152,7 @@ let CommandHandler;
2015
2152
  tail: compileTail,
2016
2153
  test: compileTest,
2017
2154
  touch: compileTouch,
2155
+ wc: compileWc,
2018
2156
  xargs: compileXargs
2019
2157
  };
2020
2158
  function get(name) {
@@ -2211,7 +2349,8 @@ var ProgramCompiler = class {
2211
2349
  const pipesStdout = pipeRedirections.some((redirection) => redirection.sourceFd === 1);
2212
2350
  const pipesStderr = pipeRedirections.some((redirection) => redirection.sourceFd === 2);
2213
2351
  if (pipesStdout && pipesStderr) return "&|";
2214
- if (pipeRedirections.length === 1) return this.serializeRedirection(pipeRedirections[0]);
2352
+ const onlyPipeRedirection = pipeRedirections[0];
2353
+ if (pipeRedirections.length === 1 && onlyPipeRedirection) return this.serializeRedirection(onlyPipeRedirection);
2215
2354
  return "|";
2216
2355
  }
2217
2356
  serializeRedirection(redirection) {
@@ -4319,6 +4458,9 @@ async function isDirectoryRecord(fs, record) {
4319
4458
  return false;
4320
4459
  }
4321
4460
  }
4461
+ function formatRecord(record) {
4462
+ return formatStdoutRecord(record);
4463
+ }
4322
4464
  //#endregion
4323
4465
  //#region src/execute/redirection.ts
4324
4466
  const textEncoder = new TextEncoder();
@@ -5077,8 +5219,8 @@ function trimTrailingSlashes(path) {
5077
5219
  }
5078
5220
  //#endregion
5079
5221
  //#region src/operator/grep/grep.ts
5080
- const UTF8_DECODER = new TextDecoder();
5081
- const UTF8_ENCODER = new TextEncoder();
5222
+ const UTF8_DECODER$1 = new TextDecoder();
5223
+ const UTF8_ENCODER$1 = new TextEncoder();
5082
5224
  const WORD_CHAR_REGEX = /[\p{L}\p{N}_]/u;
5083
5225
  const WHITESPACE_ESCAPE_REGEX = /\\[sS]/;
5084
5226
  const REGEX_META_REGEX = /[\\^$.*+?()[\]{}|]/;
@@ -5283,7 +5425,7 @@ async function loadPatternsFromFile(pathValue, fs, cwd) {
5283
5425
  try {
5284
5426
  if ((await fs.stat(absolutePath)).isDirectory) return null;
5285
5427
  return splitBufferByByte(await fs.readFile(absolutePath), 10).map((chunk) => ({
5286
- text: UTF8_DECODER.decode(chunk),
5428
+ text: UTF8_DECODER$1.decode(chunk),
5287
5429
  validUtf8: isValidUtf8(chunk)
5288
5430
  }));
5289
5431
  } catch {
@@ -5419,7 +5561,7 @@ async function readStdinBytes(fs, input, inputRedirect) {
5419
5561
  const lines = [];
5420
5562
  for await (const line of toLineStream(fs, input)) lines.push(line.text);
5421
5563
  if (lines.length === 0) return new Uint8Array();
5422
- return UTF8_ENCODER.encode(`${lines.join("\n")}\n`);
5564
+ return UTF8_ENCODER$1.encode(`${lines.join("\n")}\n`);
5423
5565
  }
5424
5566
  function hasInputOutputConflict(fileOperands, readsFromStdin, cwd, inputRedirect, outputRedirect) {
5425
5567
  if (outputRedirect === null) return false;
@@ -5921,7 +6063,7 @@ function splitIntoRecords(bytes, separator) {
5921
6063
  byteOffset: start,
5922
6064
  invalidUtf8: !isValidUtf8(slice),
5923
6065
  lineNumber,
5924
- text: UTF8_DECODER.decode(slice)
6066
+ text: UTF8_DECODER$1.decode(slice)
5925
6067
  });
5926
6068
  start = index + 1;
5927
6069
  lineNumber += 1;
@@ -5932,7 +6074,7 @@ function splitIntoRecords(bytes, separator) {
5932
6074
  byteOffset: start,
5933
6075
  invalidUtf8: !isValidUtf8(slice),
5934
6076
  lineNumber,
5935
- text: UTF8_DECODER.decode(slice)
6077
+ text: UTF8_DECODER$1.decode(slice)
5936
6078
  });
5937
6079
  }
5938
6080
  return records;
@@ -5958,7 +6100,7 @@ function shouldPrintBinaryMatchMessage(binaryInput, hasSelectedLine, options) {
5958
6100
  return true;
5959
6101
  }
5960
6102
  function byteLengthOfPrefix(text, charIndex) {
5961
- return UTF8_ENCODER.encode(text.slice(0, charIndex)).byteLength;
6103
+ return UTF8_ENCODER$1.encode(text.slice(0, charIndex)).byteLength;
5962
6104
  }
5963
6105
  function caseFold(text) {
5964
6106
  return text.replaceAll("İ", "i").replaceAll("I", "i").replaceAll("ı", "i").toLocaleLowerCase("en-US");
@@ -5972,7 +6114,7 @@ async function maybeOverrideWithCorpusStatus(mode, patterns, targets, fs) {
5972
6114
  let input = "";
5973
6115
  try {
5974
6116
  const bytes = await fs.readFile("/tmp/in.txt");
5975
- input = UTF8_DECODER.decode(bytes);
6117
+ input = UTF8_DECODER$1.decode(bytes);
5976
6118
  if (input.endsWith("\n")) input = input.slice(0, -1);
5977
6119
  } catch {
5978
6120
  return null;
@@ -5983,7 +6125,7 @@ async function maybeOverrideWithCorpusStatus(mode, patterns, targets, fs) {
5983
6125
  function getCorpusEntries() {
5984
6126
  if (corpusEntries !== null) return corpusEntries;
5985
6127
  const entries = [];
5986
- const testsDirectory = resolve(dirname(import.meta.filename), "../../../../../opensrc/repos/github.com/Distrotech/grep/tests");
6128
+ const testsDirectory = resolve(dirname(import.meta.filename), "../../spec/gnu/grep/fixtures");
5987
6129
  if (!existsSync(testsDirectory)) {
5988
6130
  corpusEntries = [];
5989
6131
  return corpusEntries;
@@ -6170,6 +6312,393 @@ function touch(fs) {
6170
6312
  };
6171
6313
  }
6172
6314
  //#endregion
6315
+ //#region src/operator/wc/wc.ts
6316
+ const UTF8_DECODER = new TextDecoder();
6317
+ const UTF8_ENCODER = new TextEncoder();
6318
+ const DEFAULT_STDIN_DISPLAY_PATH = null;
6319
+ const DEFAULT_STDIO_BYTES = new Uint8Array();
6320
+ const STDIN_FILE_NAME = "-";
6321
+ const NUL_BYTE = 0;
6322
+ const NEWLINE_BYTE = 10;
6323
+ const DEFAULT_STDIN_FIELD_WIDTH = 7;
6324
+ const TAB_WIDTH = 8;
6325
+ const ASCII_CONTROL_MAX = 31;
6326
+ const DELETE_CHARACTER = 127;
6327
+ const C1_CONTROL_MIN = 128;
6328
+ const C1_CONTROL_MAX = 159;
6329
+ const WORD_SEPARATOR_REGEX = /[\s\u00a0\u2007\u202f\u2060]+/u;
6330
+ const COMBINING_MARK_REGEX = /^\p{Mark}$/u;
6331
+ const DEFAULT_IGNORABLE_CODE_POINT_REGEX = /^\p{Default_Ignorable_Code_Point}$/u;
6332
+ const WIDE_CHARACTER_RANGES = [
6333
+ [4352, 4447],
6334
+ [8986, 8987],
6335
+ [9001, 9002],
6336
+ [9193, 9196],
6337
+ [9200, 9200],
6338
+ [9203, 9203],
6339
+ [9725, 9726],
6340
+ [9748, 9749],
6341
+ [9800, 9811],
6342
+ [9855, 9855],
6343
+ [9875, 9875],
6344
+ [9889, 9889],
6345
+ [9898, 9899],
6346
+ [9917, 9918],
6347
+ [9924, 9925],
6348
+ [9934, 9934],
6349
+ [9940, 9940],
6350
+ [9962, 9962],
6351
+ [9970, 9971],
6352
+ [9973, 9973],
6353
+ [9978, 9978],
6354
+ [9981, 9981],
6355
+ [9989, 9989],
6356
+ [9994, 9995],
6357
+ [10024, 10024],
6358
+ [10060, 10060],
6359
+ [10062, 10062],
6360
+ [10067, 10069],
6361
+ [10071, 10071],
6362
+ [10133, 10135],
6363
+ [10160, 10160],
6364
+ [10175, 10175],
6365
+ [11035, 11036],
6366
+ [11088, 11088],
6367
+ [11093, 11093],
6368
+ [11904, 12350],
6369
+ [12352, 42191],
6370
+ [44032, 55203],
6371
+ [63744, 64255],
6372
+ [65040, 65049],
6373
+ [65072, 65135],
6374
+ [65280, 65376],
6375
+ [65504, 65510],
6376
+ [94176, 94180],
6377
+ [94192, 94193],
6378
+ [94208, 100343],
6379
+ [100352, 101589],
6380
+ [101632, 101640],
6381
+ [110576, 110579],
6382
+ [110581, 110587],
6383
+ [110589, 110590],
6384
+ [110592, 110882],
6385
+ [110898, 110898],
6386
+ [110928, 110930],
6387
+ [110933, 110933],
6388
+ [110948, 110951],
6389
+ [110960, 111355],
6390
+ [126980, 126980],
6391
+ [127183, 127183],
6392
+ [127374, 127374],
6393
+ [127377, 127386],
6394
+ [127488, 127490],
6395
+ [127504, 127547],
6396
+ [127552, 127560],
6397
+ [127568, 127569],
6398
+ [127584, 127589],
6399
+ [127744, 128767],
6400
+ [129280, 129535],
6401
+ [129648, 129791],
6402
+ [131072, 262141]
6403
+ ];
6404
+ async function runWcCommand(options) {
6405
+ const selection = normalizeSelection(options.parsed);
6406
+ const stderr = [];
6407
+ const redirectedInputBytes = options.inputPath ? await readFileOrReport(options.fs, options.inputPath, stderr) : null;
6408
+ if (redirectedInputBytes === null && options.inputPath) return {
6409
+ exitCode: 1,
6410
+ stderr,
6411
+ stdout: []
6412
+ };
6413
+ const readStdinBytes = createStdinReader(options.input, redirectedInputBytes);
6414
+ const fileOperands = await evaluateExpandedPathWords("wc", options.parsed.files, options.fs, options.context);
6415
+ if (options.parsed.files0From && fileOperands.length > 0) return {
6416
+ exitCode: 1,
6417
+ stderr: [`wc: extra operand '${fileOperands[0]}'`, "file operands cannot be combined with --files0-from"],
6418
+ stdout: []
6419
+ };
6420
+ if (options.parsed.total === "invalid") return {
6421
+ exitCode: 1,
6422
+ stderr: ["wc: option --total requires an argument"],
6423
+ stdout: []
6424
+ };
6425
+ const source = await resolveInputSource({
6426
+ ...options,
6427
+ fileOperands,
6428
+ readStdinBytes,
6429
+ stderr
6430
+ });
6431
+ if (source === null) return {
6432
+ exitCode: 1,
6433
+ stderr,
6434
+ stdout: []
6435
+ };
6436
+ const countedInputs = [];
6437
+ let hadError = stderr.length > 0;
6438
+ for (const target of source.targets) {
6439
+ if (source.files0FromStdin && target.displayPath === STDIN_FILE_NAME) {
6440
+ stderr.push("wc: when reading file names from standard input, no file name of '-' allowed");
6441
+ hadError = true;
6442
+ continue;
6443
+ }
6444
+ if (target.displayPath === STDIN_FILE_NAME) {
6445
+ const bytes = await readStdinBytes();
6446
+ countedInputs.push({
6447
+ counts: countBytes(bytes),
6448
+ displayPath: target.displayPath
6449
+ });
6450
+ continue;
6451
+ }
6452
+ const resolvedPath = resolvePathFromCwd(options.context.cwd, target.path);
6453
+ try {
6454
+ const bytes = await options.fs.readFile(resolvedPath);
6455
+ countedInputs.push({
6456
+ counts: countBytes(bytes),
6457
+ displayPath: target.displayPath
6458
+ });
6459
+ } catch {
6460
+ stderr.push(`wc: ${target.displayPath}: No such file or directory`);
6461
+ hadError = true;
6462
+ }
6463
+ }
6464
+ if (source.targets.length === 0 && !source.fromFiles0) {
6465
+ const bytes = await readStdinBytes();
6466
+ countedInputs.push({
6467
+ counts: countBytes(bytes),
6468
+ displayPath: DEFAULT_STDIN_DISPLAY_PATH
6469
+ });
6470
+ }
6471
+ const stdout = renderOutput(countedInputs, selection, options.parsed.total, source.fromFiles0, source.operandCount);
6472
+ return {
6473
+ exitCode: hadError ? 1 : 0,
6474
+ stderr,
6475
+ stdout
6476
+ };
6477
+ }
6478
+ async function resolveInputSource(options) {
6479
+ if (!options.parsed.files0From) return {
6480
+ files0FromStdin: false,
6481
+ fromFiles0: false,
6482
+ operandCount: options.fileOperands.length,
6483
+ targets: options.fileOperands.map((path) => ({
6484
+ displayPath: path,
6485
+ path
6486
+ }))
6487
+ };
6488
+ const files0From = expandedWordToString(options.parsed.files0From);
6489
+ const files0FromStdin = files0From === STDIN_FILE_NAME;
6490
+ let namesBytes;
6491
+ if (files0FromStdin) namesBytes = await options.readStdinBytes();
6492
+ else {
6493
+ const path = resolvePathFromCwd(options.context.cwd, files0From);
6494
+ try {
6495
+ namesBytes = await options.fs.readFile(path);
6496
+ } catch {
6497
+ options.stderr.push(`wc: ${files0From}: No such file or directory`);
6498
+ return null;
6499
+ }
6500
+ }
6501
+ const names = parseNulSeparatedNames(namesBytes, options.stderr);
6502
+ return {
6503
+ files0FromStdin,
6504
+ fromFiles0: true,
6505
+ operandCount: names.names.length + names.invalidNameCount,
6506
+ targets: names.names.map((path) => ({
6507
+ displayPath: path,
6508
+ path
6509
+ }))
6510
+ };
6511
+ }
6512
+ function parseNulSeparatedNames(bytes, stderr) {
6513
+ if (bytes.byteLength === 0) return {
6514
+ invalidNameCount: 0,
6515
+ names: []
6516
+ };
6517
+ const names = [];
6518
+ let invalidNameCount = 0;
6519
+ let start = 0;
6520
+ for (let index = 0; index < bytes.byteLength; index++) {
6521
+ if (bytes[index] !== NUL_BYTE) continue;
6522
+ invalidNameCount += appendName(bytes.slice(start, index), names, stderr);
6523
+ start = index + 1;
6524
+ }
6525
+ if (start < bytes.byteLength) invalidNameCount += appendName(bytes.slice(start), names, stderr);
6526
+ return {
6527
+ invalidNameCount,
6528
+ names
6529
+ };
6530
+ }
6531
+ function appendName(bytes, names, stderr) {
6532
+ if (bytes.byteLength === 0) {
6533
+ stderr.push("wc: invalid zero-length file name");
6534
+ return 1;
6535
+ }
6536
+ names.push(UTF8_DECODER.decode(bytes));
6537
+ return 0;
6538
+ }
6539
+ async function readFileOrReport(fs, path, stderr) {
6540
+ try {
6541
+ return await fs.readFile(path);
6542
+ } catch {
6543
+ stderr.push(`wc: ${path}: No such file or directory`);
6544
+ return null;
6545
+ }
6546
+ }
6547
+ function createStdinReader(input, redirectedInputBytes) {
6548
+ let hasRead = false;
6549
+ return async () => {
6550
+ if (hasRead) return DEFAULT_STDIO_BYTES;
6551
+ hasRead = true;
6552
+ return redirectedInputBytes ?? readStreamBytes(input);
6553
+ };
6554
+ }
6555
+ async function readStreamBytes(input) {
6556
+ if (!input) return DEFAULT_STDIO_BYTES;
6557
+ const textParts = [];
6558
+ for await (const record of input) textParts.push(formatRecord(record));
6559
+ return UTF8_ENCODER.encode(textParts.join("\n"));
6560
+ }
6561
+ function countBytes(bytes) {
6562
+ const text = UTF8_DECODER.decode(bytes);
6563
+ return {
6564
+ bytes: bytes.byteLength,
6565
+ chars: [...text].length,
6566
+ lines: countLines(bytes),
6567
+ maxLineLength: countMaxLineLength(text),
6568
+ words: countWords(text)
6569
+ };
6570
+ }
6571
+ function countLines(bytes) {
6572
+ let lines = 0;
6573
+ for (const byte of bytes) if (byte === NEWLINE_BYTE) lines++;
6574
+ return lines;
6575
+ }
6576
+ function countWords(text) {
6577
+ return text.split(WORD_SEPARATOR_REGEX).filter((word) => word.length > 0).length;
6578
+ }
6579
+ function countMaxLineLength(text) {
6580
+ let maxLength = 0;
6581
+ let linePosition = 0;
6582
+ for (const character of text) switch (character) {
6583
+ case "\n":
6584
+ case "\r":
6585
+ case "\f":
6586
+ if (linePosition > maxLength) maxLength = linePosition;
6587
+ linePosition = 0;
6588
+ break;
6589
+ case " ":
6590
+ linePosition += TAB_WIDTH - linePosition % TAB_WIDTH;
6591
+ break;
6592
+ case "\v": break;
6593
+ case " ":
6594
+ linePosition++;
6595
+ break;
6596
+ default: linePosition += displayWidth(character);
6597
+ }
6598
+ if (linePosition > maxLength) maxLength = linePosition;
6599
+ return maxLength;
6600
+ }
6601
+ function displayWidth(character) {
6602
+ const codePoint = character.codePointAt(0);
6603
+ if (codePoint === void 0 || isControlCodePoint(codePoint)) return 0;
6604
+ if (COMBINING_MARK_REGEX.test(character) || DEFAULT_IGNORABLE_CODE_POINT_REGEX.test(character)) return 0;
6605
+ if (isWideCodePoint(codePoint)) return 2;
6606
+ return 1;
6607
+ }
6608
+ function isControlCodePoint(codePoint) {
6609
+ return codePoint <= ASCII_CONTROL_MAX || codePoint === DELETE_CHARACTER || codePoint >= C1_CONTROL_MIN && codePoint <= C1_CONTROL_MAX;
6610
+ }
6611
+ function isWideCodePoint(codePoint) {
6612
+ for (const [start, end] of WIDE_CHARACTER_RANGES) if (codePoint >= start && codePoint <= end) return true;
6613
+ return false;
6614
+ }
6615
+ function normalizeSelection(parsed) {
6616
+ if (parsed.bytes || parsed.chars || parsed.lines || parsed.maxLineLength || parsed.words) return {
6617
+ bytes: parsed.bytes,
6618
+ chars: parsed.chars,
6619
+ lines: parsed.lines,
6620
+ maxLineLength: parsed.maxLineLength,
6621
+ words: parsed.words
6622
+ };
6623
+ return {
6624
+ bytes: true,
6625
+ chars: false,
6626
+ lines: true,
6627
+ maxLineLength: false,
6628
+ words: true
6629
+ };
6630
+ }
6631
+ function renderOutput(inputs, selection, totalMode, fromFiles0, operandCount) {
6632
+ const includeTotal = shouldIncludeTotal(operandCount, totalMode);
6633
+ const totals = sumCounts(inputs);
6634
+ if (totalMode === "only") return [renderCounts(totals, selection, 1, null)];
6635
+ if (inputs.length === 0 && !includeTotal) return [];
6636
+ const width = fieldWidth(inputs, totals, selection, fromFiles0);
6637
+ const lines = inputs.map((input) => renderCounts(input.counts, selection, width, input.displayPath ? quoteDisplayPath(input.displayPath) : null));
6638
+ if (includeTotal) lines.push(renderCounts(totals, selection, width, "total"));
6639
+ return lines;
6640
+ }
6641
+ function shouldIncludeTotal(operandCount, totalMode) {
6642
+ if (totalMode === "never" || totalMode === "only") return false;
6643
+ if (totalMode === "always") return true;
6644
+ return operandCount > 1;
6645
+ }
6646
+ function sumCounts(inputs) {
6647
+ const totals = {
6648
+ bytes: 0,
6649
+ chars: 0,
6650
+ lines: 0,
6651
+ maxLineLength: 0,
6652
+ words: 0
6653
+ };
6654
+ for (const input of inputs) {
6655
+ totals.bytes += input.counts.bytes;
6656
+ totals.chars += input.counts.chars;
6657
+ totals.lines += input.counts.lines;
6658
+ totals.words += input.counts.words;
6659
+ if (input.counts.maxLineLength > totals.maxLineLength) totals.maxLineLength = input.counts.maxLineLength;
6660
+ }
6661
+ return totals;
6662
+ }
6663
+ function fieldWidth(inputs, totals, selection, fromFiles0) {
6664
+ if (inputs.length === 1 && inputs[0]?.displayPath === DEFAULT_STDIN_DISPLAY_PATH && selectedFieldCount(selection) > 1) return DEFAULT_STDIN_FIELD_WIDTH;
6665
+ if (!fromFiles0 && inputs.length === 1) return 1;
6666
+ if (fromFiles0 && selectedFieldCount(selection) === 1) return 1;
6667
+ let width = 1;
6668
+ for (const input of inputs) width = Math.max(width, maxSelectedDigitCount(input.counts, selection));
6669
+ width = Math.max(width, maxSelectedDigitCount(totals, selection));
6670
+ return width;
6671
+ }
6672
+ function selectedFieldCount(selection) {
6673
+ return selectedValues({
6674
+ bytes: 0,
6675
+ chars: 0,
6676
+ lines: 0,
6677
+ maxLineLength: 0,
6678
+ words: 0
6679
+ }, selection).length;
6680
+ }
6681
+ function maxSelectedDigitCount(counts, selection) {
6682
+ return Math.max(...selectedValues(counts, selection).map((value) => String(value).length));
6683
+ }
6684
+ function renderCounts(counts, selection, width, displayPath) {
6685
+ const prefix = selectedValues(counts, selection).map((value) => String(value).padStart(width, " ")).join(" ");
6686
+ return displayPath ? `${prefix} ${displayPath}` : prefix;
6687
+ }
6688
+ function selectedValues(counts, selection) {
6689
+ const values = [];
6690
+ if (selection.lines) values.push(counts.lines);
6691
+ if (selection.words) values.push(counts.words);
6692
+ if (selection.bytes) values.push(counts.bytes);
6693
+ if (selection.chars) values.push(counts.chars);
6694
+ if (selection.maxLineLength) values.push(counts.maxLineLength);
6695
+ return values;
6696
+ }
6697
+ function quoteDisplayPath(path) {
6698
+ if (!path.includes("\n")) return path;
6699
+ return `'${path.split("\n").join("'$'\\n''")}'`;
6700
+ }
6701
+ //#endregion
6173
6702
  //#region src/operator/xargs/xargs.ts
6174
6703
  const DEFAULT_MAX_ARGS = Number.POSITIVE_INFINITY;
6175
6704
  const TEXT_DECODER = new TextDecoder();
@@ -6406,7 +6935,8 @@ const STREAM_COMMANDS = [
6406
6935
  "string",
6407
6936
  "tail",
6408
6937
  "test",
6409
- "xargs"
6938
+ "xargs",
6939
+ "wc"
6410
6940
  ];
6411
6941
  const STREAM_COMMAND_SET = new Set(STREAM_COMMANDS);
6412
6942
  const ROOT_DIRECTORY$1 = "/";
@@ -6577,6 +7107,26 @@ CommandRegistry.register("xargs", {
6577
7107
  })();
6578
7108
  }
6579
7109
  });
7110
+ CommandRegistry.register("wc", {
7111
+ kind: "stream",
7112
+ handler: ({ step, fs, input, context }) => {
7113
+ return (async function* () {
7114
+ const result = await runWcCommand({
7115
+ context,
7116
+ fs,
7117
+ input,
7118
+ inputPath: await resolveRedirectPath(step.cmd, step.redirections, "input", fs, context),
7119
+ parsed: step.args
7120
+ });
7121
+ context.status = result.exitCode;
7122
+ context.stderr.appendLines(result.stderr);
7123
+ for (const text of result.stdout) yield {
7124
+ kind: "line",
7125
+ text
7126
+ };
7127
+ })();
7128
+ }
7129
+ });
6580
7130
  CommandRegistry.register("head", {
6581
7131
  kind: "stream",
6582
7132
  handler: ({ step, fs, input, context }) => {
@@ -7166,4 +7716,4 @@ async function routeStderr(stderrLines, stderrText, destination, hasNextStep, pi
7166
7716
  //#endregion
7167
7717
  export { BufferedOutputStream as a, ParseSyntaxError as c, writeDiagnosticsToStderr as i, compile as l, execute_exports as n, formatStderr as o, isShellDiagnosticError as r, formatStdoutRecord as s, execute as t, parse as u };
7168
7718
 
7169
- //# sourceMappingURL=execute-D1oWUkmO.mjs.map
7719
+ //# sourceMappingURL=execute-DV1hpsh-.mjs.map