shfs 0.3.3 → 0.3.4
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.
|
@@ -655,7 +655,7 @@ function compileCat(cmd) {
|
|
|
655
655
|
/**
|
|
656
656
|
* cd command handler for the AST-based compiler.
|
|
657
657
|
*/
|
|
658
|
-
const ROOT_DIRECTORY$
|
|
658
|
+
const ROOT_DIRECTORY$5 = "/";
|
|
659
659
|
/**
|
|
660
660
|
* Compile a cd command from SimpleCommandIR to StepIR.
|
|
661
661
|
*/
|
|
@@ -664,7 +664,7 @@ function compileCd(cmd) {
|
|
|
664
664
|
if (positionalArgs.length > 1) throw new Error("cd accepts at most one path");
|
|
665
665
|
return {
|
|
666
666
|
cmd: "cd",
|
|
667
|
-
args: { path: positionalArgs[0] ?? literal(ROOT_DIRECTORY$
|
|
667
|
+
args: { path: positionalArgs[0] ?? literal(ROOT_DIRECTORY$5) }
|
|
668
668
|
};
|
|
669
669
|
}
|
|
670
670
|
/**
|
|
@@ -1179,8 +1179,8 @@ function parseGrepArgs(argv) {
|
|
|
1179
1179
|
options.excludeFiles = collectStringValues(parsed, argv, "exclude");
|
|
1180
1180
|
options.excludeDir = collectStringValues(parsed, argv, "excludeDir");
|
|
1181
1181
|
options.includeFiles = collectStringValues(parsed, argv, "include");
|
|
1182
|
-
const explicitPatterns = collectExpandedValues(parsed, argv, "pattern");
|
|
1183
|
-
const patternFiles = collectExpandedValues(parsed, argv, "file");
|
|
1182
|
+
const explicitPatterns = collectExpandedValues$1(parsed, argv, "pattern");
|
|
1183
|
+
const patternFiles = collectExpandedValues$1(parsed, argv, "file");
|
|
1184
1184
|
return {
|
|
1185
1185
|
diagnostics,
|
|
1186
1186
|
explicitPatterns,
|
|
@@ -1436,7 +1436,7 @@ function assignImplicitPattern(explicitPatterns, patternFiles, positionalOperand
|
|
|
1436
1436
|
function collectStringValues(parsed, argv, canonical) {
|
|
1437
1437
|
return getValueOccurrences(parsed, argv, canonical).map((occurrence) => occurrence.value);
|
|
1438
1438
|
}
|
|
1439
|
-
function collectExpandedValues(parsed, argv, canonical) {
|
|
1439
|
+
function collectExpandedValues$1(parsed, argv, canonical) {
|
|
1440
1440
|
const values = [];
|
|
1441
1441
|
for (const occurrence of getValueOccurrences(parsed, argv, canonical)) {
|
|
1442
1442
|
if (occurrence.source === "arg") {
|
|
@@ -1449,7 +1449,7 @@ function collectExpandedValues(parsed, argv, canonical) {
|
|
|
1449
1449
|
return values;
|
|
1450
1450
|
}
|
|
1451
1451
|
function getValueOccurrences(parsed, argv, canonical) {
|
|
1452
|
-
const values = normalizeValueList(parsed.flags[canonical]);
|
|
1452
|
+
const values = normalizeValueList$1(parsed.flags[canonical]);
|
|
1453
1453
|
const valueIndices = parsed.consumedValueIndices[canonical] ?? [];
|
|
1454
1454
|
const valueSources = parsed.consumedValueSources[canonical] ?? [];
|
|
1455
1455
|
const orders = parsed.flagOccurrenceOrder[canonical] ?? [];
|
|
@@ -1478,7 +1478,7 @@ function getValueOccurrences(parsed, argv, canonical) {
|
|
|
1478
1478
|
occurrences.sort((a, b) => a.order - b.order);
|
|
1479
1479
|
return occurrences;
|
|
1480
1480
|
}
|
|
1481
|
-
function normalizeValueList(value) {
|
|
1481
|
+
function normalizeValueList$1(value) {
|
|
1482
1482
|
if (typeof value === "string") return [value];
|
|
1483
1483
|
if (Array.isArray(value)) return value;
|
|
1484
1484
|
return [];
|
|
@@ -1756,6 +1756,229 @@ function compileSet(cmd) {
|
|
|
1756
1756
|
}
|
|
1757
1757
|
};
|
|
1758
1758
|
}
|
|
1759
|
+
const COMMAND = "sort";
|
|
1760
|
+
const CHECK_OPTION = "c";
|
|
1761
|
+
const QUIET_CHECK_OPTION = "C";
|
|
1762
|
+
const FIELD_SEPARATOR_OPTION = "t";
|
|
1763
|
+
const KEY_OPTION = "k";
|
|
1764
|
+
const NUMERIC_OPTION = "n";
|
|
1765
|
+
const UNIQUE_OPTION = "u";
|
|
1766
|
+
const DEFAULT_CHECK_MODE = "none";
|
|
1767
|
+
function compileSort(command) {
|
|
1768
|
+
return {
|
|
1769
|
+
cmd: COMMAND,
|
|
1770
|
+
args: parseSortArgs(command.args)
|
|
1771
|
+
};
|
|
1772
|
+
}
|
|
1773
|
+
function createDefaultSortArgs() {
|
|
1774
|
+
return {
|
|
1775
|
+
checkMode: DEFAULT_CHECK_MODE,
|
|
1776
|
+
diagnostics: [],
|
|
1777
|
+
fieldSeparator: null,
|
|
1778
|
+
files: [],
|
|
1779
|
+
keys: [],
|
|
1780
|
+
numeric: false,
|
|
1781
|
+
unique: false
|
|
1782
|
+
};
|
|
1783
|
+
}
|
|
1784
|
+
function parseSortArgs(argv) {
|
|
1785
|
+
const args = createDefaultSortArgs();
|
|
1786
|
+
for (let index = 0; index < argv.length; index += 1) {
|
|
1787
|
+
const word = argv[index];
|
|
1788
|
+
if (!word) continue;
|
|
1789
|
+
const token = expandedWordToString(word);
|
|
1790
|
+
if (token === "--") {
|
|
1791
|
+
args.files.push(...argv.slice(index + 1));
|
|
1792
|
+
break;
|
|
1793
|
+
}
|
|
1794
|
+
if (!isOptionToken(token)) {
|
|
1795
|
+
args.files.push(word);
|
|
1796
|
+
continue;
|
|
1797
|
+
}
|
|
1798
|
+
if (token === `-${KEY_OPTION}`) {
|
|
1799
|
+
const value = argv[index + 1];
|
|
1800
|
+
addSeparatedKey(args, value, token, index);
|
|
1801
|
+
index += 1;
|
|
1802
|
+
continue;
|
|
1803
|
+
}
|
|
1804
|
+
if (token.startsWith(`-${KEY_OPTION}`)) {
|
|
1805
|
+
addKey(args, token.slice(2), token, index);
|
|
1806
|
+
continue;
|
|
1807
|
+
}
|
|
1808
|
+
if (token === `-${FIELD_SEPARATOR_OPTION}`) {
|
|
1809
|
+
const value = argv[index + 1];
|
|
1810
|
+
addSeparatedFieldSeparator(args, value, token, index);
|
|
1811
|
+
index += 1;
|
|
1812
|
+
continue;
|
|
1813
|
+
}
|
|
1814
|
+
if (token.startsWith(`-${FIELD_SEPARATOR_OPTION}`)) {
|
|
1815
|
+
addFieldSeparator(args, token.slice(2), token, index);
|
|
1816
|
+
continue;
|
|
1817
|
+
}
|
|
1818
|
+
applyShortOptions(args, token, index);
|
|
1819
|
+
}
|
|
1820
|
+
return args;
|
|
1821
|
+
}
|
|
1822
|
+
function isOptionToken(token) {
|
|
1823
|
+
return token.startsWith("-") && token !== "-";
|
|
1824
|
+
}
|
|
1825
|
+
function addSeparatedKey(args, value, token, tokenIndex) {
|
|
1826
|
+
if (!value) {
|
|
1827
|
+
addDiagnostic(args, "missing-key", "option requires an argument", token, tokenIndex);
|
|
1828
|
+
return;
|
|
1829
|
+
}
|
|
1830
|
+
addKey(args, expandedWordToString(value), token, tokenIndex);
|
|
1831
|
+
}
|
|
1832
|
+
function addKey(args, raw, token, tokenIndex) {
|
|
1833
|
+
const parsed = parseSortKey(raw, token, tokenIndex, args.diagnostics);
|
|
1834
|
+
if (parsed) args.keys.push(parsed);
|
|
1835
|
+
}
|
|
1836
|
+
function addSeparatedFieldSeparator(args, value, token, tokenIndex) {
|
|
1837
|
+
if (!value) {
|
|
1838
|
+
addDiagnostic(args, "missing-separator", "option requires an argument", token, tokenIndex);
|
|
1839
|
+
return;
|
|
1840
|
+
}
|
|
1841
|
+
addFieldSeparator(args, expandedWordToString(value), token, tokenIndex);
|
|
1842
|
+
}
|
|
1843
|
+
function addFieldSeparator(args, raw, token, tokenIndex) {
|
|
1844
|
+
const characters = Array.from(raw);
|
|
1845
|
+
const separator = characters.at(0);
|
|
1846
|
+
if (separator === void 0) {
|
|
1847
|
+
addDiagnostic(args, "empty-separator", "empty tab", token, tokenIndex);
|
|
1848
|
+
return;
|
|
1849
|
+
}
|
|
1850
|
+
if (characters.length > 1) {
|
|
1851
|
+
addDiagnostic(args, "multi-character-separator", `multi-character tab '${raw}'`, token, tokenIndex);
|
|
1852
|
+
return;
|
|
1853
|
+
}
|
|
1854
|
+
args.fieldSeparator = separator;
|
|
1855
|
+
}
|
|
1856
|
+
function applyShortOptions(args, token, tokenIndex) {
|
|
1857
|
+
const options = token.slice(1);
|
|
1858
|
+
for (const option of options) switch (option) {
|
|
1859
|
+
case CHECK_OPTION:
|
|
1860
|
+
applyCheckMode(args, "diagnose-first", token, tokenIndex);
|
|
1861
|
+
break;
|
|
1862
|
+
case QUIET_CHECK_OPTION:
|
|
1863
|
+
applyCheckMode(args, "quiet", token, tokenIndex);
|
|
1864
|
+
break;
|
|
1865
|
+
case NUMERIC_OPTION:
|
|
1866
|
+
args.numeric = true;
|
|
1867
|
+
break;
|
|
1868
|
+
case UNIQUE_OPTION:
|
|
1869
|
+
args.unique = true;
|
|
1870
|
+
break;
|
|
1871
|
+
default: addDiagnostic(args, "unknown-option", `invalid option -- '${option}'`, token, tokenIndex);
|
|
1872
|
+
}
|
|
1873
|
+
}
|
|
1874
|
+
function applyCheckMode(args, checkMode, token, tokenIndex) {
|
|
1875
|
+
if (args.checkMode !== "none" && args.checkMode !== checkMode) addDiagnostic(args, "incompatible-options", "options '-cC' are incompatible", token, tokenIndex);
|
|
1876
|
+
args.checkMode = checkMode;
|
|
1877
|
+
}
|
|
1878
|
+
function parseSortKey(raw, token, tokenIndex, diagnostics) {
|
|
1879
|
+
const commaIndex = raw.indexOf(",");
|
|
1880
|
+
const start = parseKeyPosition({
|
|
1881
|
+
diagnostics,
|
|
1882
|
+
partEnd: commaIndex === -1 ? raw.length : commaIndex,
|
|
1883
|
+
partStart: 0,
|
|
1884
|
+
raw,
|
|
1885
|
+
token,
|
|
1886
|
+
tokenIndex,
|
|
1887
|
+
type: "start"
|
|
1888
|
+
});
|
|
1889
|
+
const end = commaIndex === -1 ? null : parseKeyPosition({
|
|
1890
|
+
diagnostics,
|
|
1891
|
+
partEnd: raw.length,
|
|
1892
|
+
partStart: commaIndex + 1,
|
|
1893
|
+
raw,
|
|
1894
|
+
token,
|
|
1895
|
+
tokenIndex,
|
|
1896
|
+
type: "end"
|
|
1897
|
+
});
|
|
1898
|
+
if (!start || commaIndex !== -1 && !end) return null;
|
|
1899
|
+
return {
|
|
1900
|
+
end: end?.position ?? null,
|
|
1901
|
+
options: { numeric: start.numeric || (end?.numeric ?? false) },
|
|
1902
|
+
raw,
|
|
1903
|
+
start: start.position
|
|
1904
|
+
};
|
|
1905
|
+
}
|
|
1906
|
+
function parseKeyPosition(options) {
|
|
1907
|
+
const { diagnostics, partEnd, partStart, raw, token, tokenIndex, type } = options;
|
|
1908
|
+
const fieldDigits = readDigits(raw, partStart, partEnd);
|
|
1909
|
+
if (fieldDigits.value === "") {
|
|
1910
|
+
addInvalidNumberDiagnostic(diagnostics, raw, partStart, token, tokenIndex);
|
|
1911
|
+
return null;
|
|
1912
|
+
}
|
|
1913
|
+
const field = Number(fieldDigits.value);
|
|
1914
|
+
if (field === 0) {
|
|
1915
|
+
diagnostics.push(createSortDiagnostic("invalid-key", `invalid field specification '${raw}'`, token, tokenIndex));
|
|
1916
|
+
return null;
|
|
1917
|
+
}
|
|
1918
|
+
let cursor = fieldDigits.nextIndex;
|
|
1919
|
+
let character = null;
|
|
1920
|
+
if (raw.at(cursor) === "." && cursor < partEnd) {
|
|
1921
|
+
const characterDigits = readDigits(raw, cursor + 1, partEnd);
|
|
1922
|
+
if (characterDigits.value === "") {
|
|
1923
|
+
addCharacterNumberDiagnostic(diagnostics, raw, cursor + 1, token, tokenIndex);
|
|
1924
|
+
return null;
|
|
1925
|
+
}
|
|
1926
|
+
character = Number(characterDigits.value);
|
|
1927
|
+
if (character === 0 && type === "start") {
|
|
1928
|
+
diagnostics.push(createSortDiagnostic("invalid-key", "character offset is zero", token, tokenIndex), createSortDiagnostic("invalid-key", `invalid field specification '${raw}'`, token, tokenIndex));
|
|
1929
|
+
return null;
|
|
1930
|
+
}
|
|
1931
|
+
cursor = characterDigits.nextIndex;
|
|
1932
|
+
}
|
|
1933
|
+
const ordering = readOrderingOptions(raw, cursor, partEnd, token, tokenIndex, diagnostics);
|
|
1934
|
+
if (!ordering) return null;
|
|
1935
|
+
return {
|
|
1936
|
+
numeric: ordering.numeric,
|
|
1937
|
+
position: {
|
|
1938
|
+
character,
|
|
1939
|
+
field
|
|
1940
|
+
}
|
|
1941
|
+
};
|
|
1942
|
+
}
|
|
1943
|
+
function readDigits(text, start, end) {
|
|
1944
|
+
let cursor = start;
|
|
1945
|
+
while (cursor < end) {
|
|
1946
|
+
const character = text.at(cursor);
|
|
1947
|
+
if (character === void 0 || character < "0" || character > "9") break;
|
|
1948
|
+
cursor += 1;
|
|
1949
|
+
}
|
|
1950
|
+
return {
|
|
1951
|
+
nextIndex: cursor,
|
|
1952
|
+
value: text.slice(start, cursor)
|
|
1953
|
+
};
|
|
1954
|
+
}
|
|
1955
|
+
function readOrderingOptions(raw, start, end, token, tokenIndex, diagnostics) {
|
|
1956
|
+
let numeric = false;
|
|
1957
|
+
for (let cursor = start; cursor < end; cursor += 1) {
|
|
1958
|
+
if (raw.at(cursor) === NUMERIC_OPTION) {
|
|
1959
|
+
numeric = true;
|
|
1960
|
+
continue;
|
|
1961
|
+
}
|
|
1962
|
+
diagnostics.push(createSortDiagnostic("invalid-key", `invalid count at start of '${raw.slice(cursor)}'`, token, tokenIndex));
|
|
1963
|
+
return null;
|
|
1964
|
+
}
|
|
1965
|
+
return { numeric };
|
|
1966
|
+
}
|
|
1967
|
+
function addInvalidNumberDiagnostic(diagnostics, raw, position, token, tokenIndex) {
|
|
1968
|
+
diagnostics.push(createSortDiagnostic("invalid-key", "invalid number after ','", token, tokenIndex), createSortDiagnostic("invalid-key", `invalid count at start of '${raw.slice(position)}'`, token, tokenIndex));
|
|
1969
|
+
}
|
|
1970
|
+
function addCharacterNumberDiagnostic(diagnostics, raw, position, token, tokenIndex) {
|
|
1971
|
+
diagnostics.push(createSortDiagnostic("invalid-key", "invalid number after '.'", token, tokenIndex), createSortDiagnostic("invalid-key", `invalid count at start of '${raw.slice(position)}'`, token, tokenIndex));
|
|
1972
|
+
}
|
|
1973
|
+
function addDiagnostic(args, code, message, token, tokenIndex) {
|
|
1974
|
+
args.diagnostics.push(createSortDiagnostic(code, message, token, tokenIndex));
|
|
1975
|
+
}
|
|
1976
|
+
function createSortDiagnostic(code, message, token, tokenIndex) {
|
|
1977
|
+
return createCommandDiagnostic(COMMAND, code, message, {
|
|
1978
|
+
token,
|
|
1979
|
+
tokenIndex
|
|
1980
|
+
});
|
|
1981
|
+
}
|
|
1759
1982
|
function compileString(cmd) {
|
|
1760
1983
|
const [subcommand, ...operands] = cmd.args;
|
|
1761
1984
|
if (!subcommand) throw new Error("string requires a subcommand");
|
|
@@ -1861,6 +2084,109 @@ function compileTouch(cmd) {
|
|
|
1861
2084
|
}
|
|
1862
2085
|
};
|
|
1863
2086
|
}
|
|
2087
|
+
/**
|
|
2088
|
+
* tree command handler for the AST-based compiler.
|
|
2089
|
+
*/
|
|
2090
|
+
const parseTreeArgs = createWordParser({
|
|
2091
|
+
ascii: {
|
|
2092
|
+
short: "A",
|
|
2093
|
+
takesValue: false
|
|
2094
|
+
},
|
|
2095
|
+
classify: {
|
|
2096
|
+
short: "F",
|
|
2097
|
+
takesValue: false
|
|
2098
|
+
},
|
|
2099
|
+
dirsOnly: {
|
|
2100
|
+
short: "d",
|
|
2101
|
+
takesValue: false
|
|
2102
|
+
},
|
|
2103
|
+
excludePattern: {
|
|
2104
|
+
short: "I",
|
|
2105
|
+
takesValue: true,
|
|
2106
|
+
multiple: true,
|
|
2107
|
+
allowFlagLikeValue: true
|
|
2108
|
+
},
|
|
2109
|
+
fullPath: {
|
|
2110
|
+
short: "f",
|
|
2111
|
+
takesValue: false
|
|
2112
|
+
},
|
|
2113
|
+
includePattern: {
|
|
2114
|
+
short: "P",
|
|
2115
|
+
takesValue: true,
|
|
2116
|
+
multiple: true,
|
|
2117
|
+
allowFlagLikeValue: true
|
|
2118
|
+
},
|
|
2119
|
+
matchDirs: {
|
|
2120
|
+
long: "matchdirs",
|
|
2121
|
+
takesValue: false
|
|
2122
|
+
},
|
|
2123
|
+
maxDepth: {
|
|
2124
|
+
short: "L",
|
|
2125
|
+
takesValue: true
|
|
2126
|
+
},
|
|
2127
|
+
noReport: {
|
|
2128
|
+
long: "noreport",
|
|
2129
|
+
takesValue: false
|
|
2130
|
+
},
|
|
2131
|
+
prune: {
|
|
2132
|
+
long: "prune",
|
|
2133
|
+
takesValue: false
|
|
2134
|
+
},
|
|
2135
|
+
showAll: {
|
|
2136
|
+
short: "a",
|
|
2137
|
+
takesValue: false
|
|
2138
|
+
}
|
|
2139
|
+
}, expandedWordToString);
|
|
2140
|
+
function compileTree(command) {
|
|
2141
|
+
const parsed = parseTreeArgs(command.args);
|
|
2142
|
+
return {
|
|
2143
|
+
cmd: "tree",
|
|
2144
|
+
args: {
|
|
2145
|
+
ascii: parsed.flags.ascii === true,
|
|
2146
|
+
classify: parsed.flags.classify === true,
|
|
2147
|
+
dirsOnly: parsed.flags.dirsOnly === true,
|
|
2148
|
+
excludePatterns: collectExpandedValues(parsed, command.args, "excludePattern"),
|
|
2149
|
+
fullPath: parsed.flags.fullPath === true,
|
|
2150
|
+
includePatterns: collectExpandedValues(parsed, command.args, "includePattern"),
|
|
2151
|
+
matchDirs: parsed.flags.matchDirs === true,
|
|
2152
|
+
maxDepth: parseMaxDepth(parsed.flags.maxDepth),
|
|
2153
|
+
noReport: parsed.flags.noReport === true,
|
|
2154
|
+
paths: parsed.positionalWords.length === 0 ? [literal(".")] : parsed.positionalWords,
|
|
2155
|
+
prune: parsed.flags.prune === true,
|
|
2156
|
+
showAll: parsed.flags.showAll === true
|
|
2157
|
+
}
|
|
2158
|
+
};
|
|
2159
|
+
}
|
|
2160
|
+
function parseMaxDepth(value) {
|
|
2161
|
+
if (typeof value !== "string") return null;
|
|
2162
|
+
const maxDepth = Number.parseInt(value, 10);
|
|
2163
|
+
if (!Number.isFinite(maxDepth) || maxDepth < 0) throw new Error(`tree: invalid level, '${value}'`);
|
|
2164
|
+
return maxDepth;
|
|
2165
|
+
}
|
|
2166
|
+
function collectExpandedValues(parsed, argv, canonical) {
|
|
2167
|
+
const values = [];
|
|
2168
|
+
const rawValues = normalizeValueList(parsed.flags[canonical]);
|
|
2169
|
+
const valueIndices = parsed.consumedValueIndices[canonical] ?? [];
|
|
2170
|
+
const valueSources = parsed.consumedValueSources[canonical] ?? [];
|
|
2171
|
+
const count = Math.min(rawValues.length, valueIndices.length);
|
|
2172
|
+
for (let index = 0; index < count; index += 1) {
|
|
2173
|
+
const rawValue = rawValues[index];
|
|
2174
|
+
const valueIndex = valueIndices[index];
|
|
2175
|
+
const source = valueSources[index];
|
|
2176
|
+
if (rawValue === void 0 || valueIndex === void 0) continue;
|
|
2177
|
+
if (source === "arg") {
|
|
2178
|
+
values.push(argv[valueIndex] ?? literal(rawValue));
|
|
2179
|
+
continue;
|
|
2180
|
+
}
|
|
2181
|
+
values.push(literal(rawValue));
|
|
2182
|
+
}
|
|
2183
|
+
return values;
|
|
2184
|
+
}
|
|
2185
|
+
function normalizeValueList(value) {
|
|
2186
|
+
if (typeof value === "string") return [value];
|
|
2187
|
+
if (Array.isArray(value)) return value.filter((item) => typeof item === "string");
|
|
2188
|
+
return [];
|
|
2189
|
+
}
|
|
1864
2190
|
const DEFAULT_TOTAL_MODE = "auto";
|
|
1865
2191
|
function compileWc(command) {
|
|
1866
2192
|
return {
|
|
@@ -2148,10 +2474,12 @@ let CommandHandler;
|
|
|
2148
2474
|
read: compileRead,
|
|
2149
2475
|
rm: compileRm,
|
|
2150
2476
|
set: compileSet,
|
|
2477
|
+
sort: compileSort,
|
|
2151
2478
|
string: compileString,
|
|
2152
2479
|
tail: compileTail,
|
|
2153
2480
|
test: compileTest,
|
|
2154
2481
|
touch: compileTouch,
|
|
2482
|
+
tree: compileTree,
|
|
2155
2483
|
wc: compileWc,
|
|
2156
2484
|
xargs: compileXargs
|
|
2157
2485
|
};
|
|
@@ -4238,8 +4566,8 @@ function toErrorMessage$1(diagnostic) {
|
|
|
4238
4566
|
//#endregion
|
|
4239
4567
|
//#region src/execute/path.ts
|
|
4240
4568
|
const MULTIPLE_SLASH_REGEX$2 = /\/+/g;
|
|
4241
|
-
const ROOT_DIRECTORY$
|
|
4242
|
-
const TRAILING_SLASH_REGEX$
|
|
4569
|
+
const ROOT_DIRECTORY$4 = "/";
|
|
4570
|
+
const TRAILING_SLASH_REGEX$3 = /\/+$/;
|
|
4243
4571
|
const VARIABLE_REFERENCE_REGEX = /\$([A-Za-z_][A-Za-z0-9_]*)/g;
|
|
4244
4572
|
const NO_GLOB_MATCH_MESSAGE = "no matches found";
|
|
4245
4573
|
async function collectOutputRecords(result) {
|
|
@@ -4265,7 +4593,7 @@ function expandVariables(input, context) {
|
|
|
4265
4593
|
});
|
|
4266
4594
|
}
|
|
4267
4595
|
function normalizeAbsolutePath(path) {
|
|
4268
|
-
const segments = (path.startsWith(ROOT_DIRECTORY$
|
|
4596
|
+
const segments = (path.startsWith(ROOT_DIRECTORY$4) ? path : `${ROOT_DIRECTORY$4}${path}`).replace(MULTIPLE_SLASH_REGEX$2, "/").split(ROOT_DIRECTORY$4);
|
|
4269
4597
|
const normalizedSegments = [];
|
|
4270
4598
|
for (const segment of segments) {
|
|
4271
4599
|
if (segment === "" || segment === ".") continue;
|
|
@@ -4275,17 +4603,17 @@ function normalizeAbsolutePath(path) {
|
|
|
4275
4603
|
}
|
|
4276
4604
|
normalizedSegments.push(segment);
|
|
4277
4605
|
}
|
|
4278
|
-
const normalizedPath = `${ROOT_DIRECTORY$
|
|
4279
|
-
return normalizedPath === "" ? ROOT_DIRECTORY$
|
|
4606
|
+
const normalizedPath = `${ROOT_DIRECTORY$4}${normalizedSegments.join(ROOT_DIRECTORY$4)}`;
|
|
4607
|
+
return normalizedPath === "" ? ROOT_DIRECTORY$4 : normalizedPath;
|
|
4280
4608
|
}
|
|
4281
4609
|
function normalizeCwd(cwd) {
|
|
4282
|
-
if (cwd === "") return ROOT_DIRECTORY$
|
|
4283
|
-
const trimmed = normalizeAbsolutePath(cwd).replace(TRAILING_SLASH_REGEX$
|
|
4284
|
-
return trimmed === "" ? ROOT_DIRECTORY$
|
|
4610
|
+
if (cwd === "") return ROOT_DIRECTORY$4;
|
|
4611
|
+
const trimmed = normalizeAbsolutePath(cwd).replace(TRAILING_SLASH_REGEX$3, "");
|
|
4612
|
+
return trimmed === "" ? ROOT_DIRECTORY$4 : trimmed;
|
|
4285
4613
|
}
|
|
4286
4614
|
function resolvePathFromCwd(cwd, path) {
|
|
4287
4615
|
if (path === "") return cwd;
|
|
4288
|
-
if (path.startsWith(ROOT_DIRECTORY$
|
|
4616
|
+
if (path.startsWith(ROOT_DIRECTORY$4)) return normalizeAbsolutePath(path);
|
|
4289
4617
|
return normalizeAbsolutePath(`${cwd}/${path}`);
|
|
4290
4618
|
}
|
|
4291
4619
|
function resolvePathsFromCwd(cwd, paths) {
|
|
@@ -4300,7 +4628,7 @@ async function readDirectoryPaths(fs, directoryPath) {
|
|
|
4300
4628
|
children.sort((left, right) => left.localeCompare(right));
|
|
4301
4629
|
return children;
|
|
4302
4630
|
}
|
|
4303
|
-
async function walkFilesystemEntries(fs, rootDir = ROOT_DIRECTORY$
|
|
4631
|
+
async function walkFilesystemEntries(fs, rootDir = ROOT_DIRECTORY$4) {
|
|
4304
4632
|
const normalizedRoot = normalizeAbsolutePath(rootDir);
|
|
4305
4633
|
if (!(await fs.stat(normalizedRoot)).isDirectory) throw new Error(`Not a directory: ${normalizedRoot}`);
|
|
4306
4634
|
const entries = [];
|
|
@@ -4322,12 +4650,12 @@ async function walkFilesystemEntries(fs, rootDir = ROOT_DIRECTORY$3) {
|
|
|
4322
4650
|
return entries;
|
|
4323
4651
|
}
|
|
4324
4652
|
function toRelativePathFromCwd$1(path, cwd) {
|
|
4325
|
-
if (cwd === ROOT_DIRECTORY$
|
|
4326
|
-
if (path === ROOT_DIRECTORY$
|
|
4327
|
-
return path.startsWith(ROOT_DIRECTORY$
|
|
4653
|
+
if (cwd === ROOT_DIRECTORY$4) {
|
|
4654
|
+
if (path === ROOT_DIRECTORY$4) return null;
|
|
4655
|
+
return path.startsWith(ROOT_DIRECTORY$4) ? path.slice(1) : path;
|
|
4328
4656
|
}
|
|
4329
4657
|
if (path === cwd) return null;
|
|
4330
|
-
const prefix = `${cwd}${ROOT_DIRECTORY$
|
|
4658
|
+
const prefix = `${cwd}${ROOT_DIRECTORY$4}`;
|
|
4331
4659
|
if (!path.startsWith(prefix)) return null;
|
|
4332
4660
|
return path.slice(prefix.length);
|
|
4333
4661
|
}
|
|
@@ -4335,12 +4663,12 @@ function toGlobCandidate(entry, cwd, isAbsolutePattern, directoryOnly) {
|
|
|
4335
4663
|
if (directoryOnly && !entry.isDirectory) return null;
|
|
4336
4664
|
const basePath = isAbsolutePattern ? entry.path : toRelativePathFromCwd$1(entry.path, cwd);
|
|
4337
4665
|
if (!basePath || basePath === "") return null;
|
|
4338
|
-
if (directoryOnly) return `${basePath}${ROOT_DIRECTORY$
|
|
4666
|
+
if (directoryOnly) return `${basePath}${ROOT_DIRECTORY$4}`;
|
|
4339
4667
|
return basePath;
|
|
4340
4668
|
}
|
|
4341
4669
|
async function expandGlobPattern(pattern, fs, context) {
|
|
4342
|
-
const directoryOnly = pattern.endsWith(ROOT_DIRECTORY$
|
|
4343
|
-
const isAbsolutePattern = pattern.startsWith(ROOT_DIRECTORY$
|
|
4670
|
+
const directoryOnly = pattern.endsWith(ROOT_DIRECTORY$4);
|
|
4671
|
+
const isAbsolutePattern = pattern.startsWith(ROOT_DIRECTORY$4);
|
|
4344
4672
|
const matcher = picomatch(pattern, {
|
|
4345
4673
|
bash: true,
|
|
4346
4674
|
dot: false
|
|
@@ -4405,28 +4733,10 @@ async function evaluateExpandedWordPart(part, fs, context) {
|
|
|
4405
4733
|
}
|
|
4406
4734
|
//#endregion
|
|
4407
4735
|
//#region src/execute/records.ts
|
|
4408
|
-
async function* toLineStream(fs, input) {
|
|
4409
|
-
for await (const record of input) {
|
|
4410
|
-
if (record.kind === "line") {
|
|
4411
|
-
yield record;
|
|
4412
|
-
continue;
|
|
4413
|
-
}
|
|
4414
|
-
if (record.kind === "file") {
|
|
4415
|
-
yield* fileRecordToLines(fs, record);
|
|
4416
|
-
continue;
|
|
4417
|
-
}
|
|
4418
|
-
yield {
|
|
4419
|
-
kind: "line",
|
|
4420
|
-
text: JSON.stringify(record.value)
|
|
4421
|
-
};
|
|
4422
|
-
}
|
|
4423
|
-
}
|
|
4424
4736
|
/**
|
|
4425
|
-
* Converts
|
|
4426
|
-
*
|
|
4427
|
-
*
|
|
4428
|
-
* line-oriented transducers (tail, head) receiving piped input from commands
|
|
4429
|
-
* like `find` that produce path listings.
|
|
4737
|
+
* Converts records into stdin-style line text. Unlike `toLineStream`, this does
|
|
4738
|
+
* not read FileRecord contents. FileRecords are rendered as paths, matching the
|
|
4739
|
+
* shell pipe boundary where downstream line-oriented commands consume text.
|
|
4430
4740
|
*/
|
|
4431
4741
|
async function* toFormattedLineStream(input) {
|
|
4432
4742
|
for await (const record of input) {
|
|
@@ -4440,16 +4750,6 @@ async function* toFormattedLineStream(input) {
|
|
|
4440
4750
|
};
|
|
4441
4751
|
}
|
|
4442
4752
|
}
|
|
4443
|
-
async function* fileRecordToLines(fs, record) {
|
|
4444
|
-
if (await isDirectoryRecord(fs, record)) return;
|
|
4445
|
-
let lineNum = 1;
|
|
4446
|
-
for await (const text of fs.readLines(record.path)) yield {
|
|
4447
|
-
kind: "line",
|
|
4448
|
-
text,
|
|
4449
|
-
file: record.path,
|
|
4450
|
-
lineNum: lineNum++
|
|
4451
|
-
};
|
|
4452
|
-
}
|
|
4453
4753
|
async function isDirectoryRecord(fs, record) {
|
|
4454
4754
|
if (record.isDirectory !== void 0) return record.isDirectory;
|
|
4455
4755
|
try {
|
|
@@ -4458,14 +4758,12 @@ async function isDirectoryRecord(fs, record) {
|
|
|
4458
4758
|
return false;
|
|
4459
4759
|
}
|
|
4460
4760
|
}
|
|
4461
|
-
function formatRecord(record) {
|
|
4462
|
-
return formatStdoutRecord(record);
|
|
4463
|
-
}
|
|
4464
4761
|
//#endregion
|
|
4465
4762
|
//#region src/execute/redirection.ts
|
|
4466
4763
|
const textEncoder = new TextEncoder();
|
|
4467
4764
|
const textDecoder = new TextDecoder();
|
|
4468
4765
|
const FD_TARGET_REGEX$1 = /^&[0-9]+$/;
|
|
4766
|
+
const NULL_DEVICE_PATH = "/dev/null";
|
|
4469
4767
|
function getSourceFd$1(redirection) {
|
|
4470
4768
|
return redirection.sourceFd ?? (redirection.kind === "input" ? 0 : 1);
|
|
4471
4769
|
}
|
|
@@ -4572,6 +4870,7 @@ async function readExistingFileText(fs, path) {
|
|
|
4572
4870
|
}
|
|
4573
4871
|
}
|
|
4574
4872
|
async function writeTextToFile(fs, path, content, options) {
|
|
4873
|
+
if (isNullDevicePath(path)) return;
|
|
4575
4874
|
if (!(options.append ?? false)) {
|
|
4576
4875
|
await fs.writeFile(path, textEncoder.encode(content));
|
|
4577
4876
|
return;
|
|
@@ -4581,8 +4880,12 @@ async function writeTextToFile(fs, path, content, options) {
|
|
|
4581
4880
|
await fs.writeFile(path, textEncoder.encode(`${existing}${separator}${content}`));
|
|
4582
4881
|
}
|
|
4583
4882
|
async function ensureNoclobberWritable(fs, path) {
|
|
4883
|
+
if (isNullDevicePath(path)) return true;
|
|
4584
4884
|
return !await fs.exists(path);
|
|
4585
4885
|
}
|
|
4886
|
+
function isNullDevicePath(path) {
|
|
4887
|
+
return path === NULL_DEVICE_PATH;
|
|
4888
|
+
}
|
|
4586
4889
|
//#endregion
|
|
4587
4890
|
//#region src/builtin/cd/cd.ts
|
|
4588
4891
|
const cd = async (runtime, args) => {
|
|
@@ -4616,21 +4919,9 @@ const VARIABLE_NAME_REGEX$1 = /^[A-Za-z_][A-Za-z0-9_]*$/;
|
|
|
4616
4919
|
async function readFirstValue(runtime) {
|
|
4617
4920
|
if (!runtime.input) return null;
|
|
4618
4921
|
let firstValue = null;
|
|
4619
|
-
for await (const
|
|
4620
|
-
const value = await recordToText(runtime, record);
|
|
4621
|
-
if (value !== null && firstValue === null) firstValue = value;
|
|
4622
|
-
}
|
|
4922
|
+
for await (const line of runtime.stdin.lines()) if (firstValue === null) firstValue = line;
|
|
4623
4923
|
return firstValue;
|
|
4624
4924
|
}
|
|
4625
|
-
async function recordToText(runtime, record) {
|
|
4626
|
-
if (record.kind === "line") return record.text;
|
|
4627
|
-
if (record.kind === "file") {
|
|
4628
|
-
if (await isDirectoryRecord(runtime.fs, record)) return null;
|
|
4629
|
-
for await (const line of runtime.fs.readLines(record.path)) return line;
|
|
4630
|
-
return "";
|
|
4631
|
-
}
|
|
4632
|
-
return JSON.stringify(record.value);
|
|
4633
|
-
}
|
|
4634
4925
|
const read = (runtime, args) => {
|
|
4635
4926
|
return (async function* () {
|
|
4636
4927
|
const name = await evaluateExpandedWord(args.name, runtime.fs, runtime.context);
|
|
@@ -4661,14 +4952,21 @@ const set = (runtime, args) => {
|
|
|
4661
4952
|
};
|
|
4662
4953
|
//#endregion
|
|
4663
4954
|
//#region src/builtin/string/string.ts
|
|
4955
|
+
async function collectStdinLines(runtime) {
|
|
4956
|
+
if (!runtime.input) return [];
|
|
4957
|
+
const lines = [];
|
|
4958
|
+
for await (const line of runtime.stdin.lines()) lines.push(line);
|
|
4959
|
+
return lines;
|
|
4960
|
+
}
|
|
4664
4961
|
function replace(runtime, operands) {
|
|
4665
4962
|
return (async function* () {
|
|
4666
4963
|
if (operands[0]?.startsWith("-")) throw new Error(`string replace: unsupported flag: ${operands[0]}`);
|
|
4667
|
-
if (operands.length <
|
|
4964
|
+
if (operands.length < 2) throw new Error("string replace requires pattern replacement text");
|
|
4668
4965
|
const pattern = operands.at(0);
|
|
4669
4966
|
const replacement = operands.at(1);
|
|
4670
|
-
const inputs = operands.slice(2);
|
|
4671
4967
|
if (pattern === void 0 || replacement === void 0) throw new Error("string replace requires pattern replacement text");
|
|
4968
|
+
if (operands.length === 2 && !runtime.input) throw new Error("string replace requires pattern replacement text");
|
|
4969
|
+
const inputs = operands.length > 2 ? operands.slice(2) : await collectStdinLines(runtime);
|
|
4672
4970
|
if (inputs.length === 0) {
|
|
4673
4971
|
runtime.context.status = 1;
|
|
4674
4972
|
return;
|
|
@@ -4680,29 +4978,44 @@ function replace(runtime, operands) {
|
|
|
4680
4978
|
runtime.context.status = 0;
|
|
4681
4979
|
})();
|
|
4682
4980
|
}
|
|
4981
|
+
async function parseMatchInvocation(runtime, operands) {
|
|
4982
|
+
let quiet = false;
|
|
4983
|
+
let offset = 0;
|
|
4984
|
+
while (operands[offset]?.startsWith("-")) {
|
|
4985
|
+
const flag = operands[offset];
|
|
4986
|
+
if (flag === "-q" && !quiet) {
|
|
4987
|
+
quiet = true;
|
|
4988
|
+
offset += 1;
|
|
4989
|
+
continue;
|
|
4990
|
+
}
|
|
4991
|
+
throw new Error(`string match: unsupported flag: ${flag}`);
|
|
4992
|
+
}
|
|
4993
|
+
const filtered = operands.slice(offset);
|
|
4994
|
+
const [pattern] = filtered;
|
|
4995
|
+
if (!pattern) throw new Error("string match requires pattern and value");
|
|
4996
|
+
if (filtered.length > 2) throw new Error("string match: unsupported arguments");
|
|
4997
|
+
if (filtered.length === 1 && !runtime.input) throw new Error("string match requires pattern and value");
|
|
4998
|
+
const values = filtered.length > 1 ? filtered.slice(1) : await collectStdinLines(runtime);
|
|
4999
|
+
return {
|
|
5000
|
+
pattern,
|
|
5001
|
+
quiet,
|
|
5002
|
+
values
|
|
5003
|
+
};
|
|
5004
|
+
}
|
|
4683
5005
|
function match(runtime, operands) {
|
|
4684
5006
|
return (async function* () {
|
|
4685
|
-
|
|
4686
|
-
|
|
4687
|
-
|
|
4688
|
-
|
|
4689
|
-
if (
|
|
4690
|
-
|
|
4691
|
-
|
|
4692
|
-
|
|
4693
|
-
|
|
4694
|
-
|
|
4695
|
-
}
|
|
4696
|
-
|
|
4697
|
-
const [pattern, value] = filtered;
|
|
4698
|
-
if (!(pattern && value !== void 0)) throw new Error("string match requires pattern and value");
|
|
4699
|
-
if (filtered.length > 2) throw new Error("string match: unsupported arguments");
|
|
4700
|
-
const isMatch = picomatch(pattern, { dot: true })(value);
|
|
4701
|
-
runtime.context.status = isMatch ? 0 : 1;
|
|
4702
|
-
if (isMatch && !quiet) yield {
|
|
4703
|
-
kind: "line",
|
|
4704
|
-
text: value
|
|
4705
|
-
};
|
|
5007
|
+
const { pattern, quiet, values } = await parseMatchInvocation(runtime, operands);
|
|
5008
|
+
const matcher = picomatch(pattern, { dot: true });
|
|
5009
|
+
let matched = false;
|
|
5010
|
+
for (const value of values) {
|
|
5011
|
+
if (!matcher(value)) continue;
|
|
5012
|
+
matched = true;
|
|
5013
|
+
if (!quiet) yield {
|
|
5014
|
+
kind: "line",
|
|
5015
|
+
text: value
|
|
5016
|
+
};
|
|
5017
|
+
}
|
|
5018
|
+
runtime.context.status = matched ? 0 : 1;
|
|
4706
5019
|
})();
|
|
4707
5020
|
}
|
|
4708
5021
|
const string = (runtime, args) => {
|
|
@@ -4851,16 +5164,16 @@ function cat(fs, options) {
|
|
|
4851
5164
|
}
|
|
4852
5165
|
//#endregion
|
|
4853
5166
|
//#region src/operator/cp/cp.ts
|
|
4854
|
-
const TRAILING_SLASH_REGEX$
|
|
5167
|
+
const TRAILING_SLASH_REGEX$2 = /\/+$/;
|
|
4855
5168
|
const MULTIPLE_SLASH_REGEX$1 = /\/+/g;
|
|
4856
5169
|
function trimTrailingSlash$2(path) {
|
|
4857
5170
|
if (path === "/") return path;
|
|
4858
|
-
return path.replace(TRAILING_SLASH_REGEX$
|
|
5171
|
+
return path.replace(TRAILING_SLASH_REGEX$2, "");
|
|
4859
5172
|
}
|
|
4860
5173
|
function joinPath$1(base, suffix) {
|
|
4861
5174
|
return `${trimTrailingSlash$2(base)}/${suffix}`.replace(MULTIPLE_SLASH_REGEX$1, "/");
|
|
4862
5175
|
}
|
|
4863
|
-
function basename$
|
|
5176
|
+
function basename$4(path) {
|
|
4864
5177
|
const normalized = trimTrailingSlash$2(path);
|
|
4865
5178
|
const slashIndex = normalized.lastIndexOf("/");
|
|
4866
5179
|
if (slashIndex === -1) return normalized;
|
|
@@ -4911,7 +5224,7 @@ async function copyDirectoryRecursive(fs, srcDir, destDir, force, interactive) {
|
|
|
4911
5224
|
if (!current) continue;
|
|
4912
5225
|
const childPaths = await readDirectory(current.sourcePath);
|
|
4913
5226
|
for (const childPath of childPaths) {
|
|
4914
|
-
const childName = basename$
|
|
5227
|
+
const childName = basename$4(childPath);
|
|
4915
5228
|
const targetPath = joinPath$1(current.targetPath, childName);
|
|
4916
5229
|
if ((await fs.stat(childPath)).isDirectory) {
|
|
4917
5230
|
await ensureDirectory(targetPath);
|
|
@@ -4932,7 +5245,7 @@ function cp(fs) {
|
|
|
4932
5245
|
if (srcs.length > 1 && !destinationIsDirectory) throw new Error("cp destination must be a directory for multiple sources");
|
|
4933
5246
|
for (const src of srcs) {
|
|
4934
5247
|
const srcStat = await fs.stat(src);
|
|
4935
|
-
const targetPath = destinationIsDirectory || srcs.length > 1 ? joinPath$1(dest, basename$
|
|
5248
|
+
const targetPath = destinationIsDirectory || srcs.length > 1 ? joinPath$1(dest, basename$4(src)) : dest;
|
|
4936
5249
|
if (srcStat.isDirectory) {
|
|
4937
5250
|
if (!recursive) throw new Error(`cp: omitting directory "${src}" (use -r)`);
|
|
4938
5251
|
await copyDirectoryRecursive(fs, src, targetPath, force, interactive);
|
|
@@ -5004,12 +5317,12 @@ async function* walkEntry(fs, context, entry, args, predicateBranches, state, ha
|
|
|
5004
5317
|
childStat = await fs.stat(childAbsolutePath);
|
|
5005
5318
|
} catch {
|
|
5006
5319
|
state.hadError = true;
|
|
5007
|
-
writeDiagnosticsToStderr(context, [createRuntimeDiagnostic("find", "missing-path", "No such file or directory", { path: appendDisplayPath(entry.displayPath, basename$
|
|
5320
|
+
writeDiagnosticsToStderr(context, [createRuntimeDiagnostic("find", "missing-path", "No such file or directory", { path: appendDisplayPath(entry.displayPath, basename$3(childAbsolutePath)) })]);
|
|
5008
5321
|
continue;
|
|
5009
5322
|
}
|
|
5010
5323
|
yield* walkEntry(fs, context, {
|
|
5011
5324
|
absolutePath: childAbsolutePath,
|
|
5012
|
-
displayPath: appendDisplayPath(entry.displayPath, basename$
|
|
5325
|
+
displayPath: appendDisplayPath(entry.displayPath, basename$3(childAbsolutePath)),
|
|
5013
5326
|
depth: entry.depth + 1,
|
|
5014
5327
|
isDirectory: childStat.isDirectory,
|
|
5015
5328
|
size: childStat.size
|
|
@@ -5113,7 +5426,7 @@ function matchesBranch(entry, entryType, branch, childPaths) {
|
|
|
5113
5426
|
return true;
|
|
5114
5427
|
}
|
|
5115
5428
|
function matchesPredicate(entry, entryType, predicate, childPaths) {
|
|
5116
|
-
if (predicate.kind === "name") return predicate.matcher(basename$
|
|
5429
|
+
if (predicate.kind === "name") return predicate.matcher(basename$3(entry.displayPath));
|
|
5117
5430
|
if (predicate.kind === "path") return predicate.matcher(entry.displayPath);
|
|
5118
5431
|
if (predicate.kind === "regex") return predicate.matcher(entry.displayPath);
|
|
5119
5432
|
if (predicate.kind === "constant") return predicate.value;
|
|
@@ -5172,7 +5485,7 @@ function appendDisplayPath(parentPath, childName) {
|
|
|
5172
5485
|
if (parentPath === ".") return `./${childName}`;
|
|
5173
5486
|
return `${parentPath}/${childName}`;
|
|
5174
5487
|
}
|
|
5175
|
-
function basename$
|
|
5488
|
+
function basename$3(path) {
|
|
5176
5489
|
if (path === "/") return "/";
|
|
5177
5490
|
const normalized = trimTrailingSlashes(path);
|
|
5178
5491
|
const slashIndex = normalized.lastIndexOf("/");
|
|
@@ -5218,6 +5531,54 @@ function trimTrailingSlashes(path) {
|
|
|
5218
5531
|
return path.replace(/\/+$/g, "");
|
|
5219
5532
|
}
|
|
5220
5533
|
//#endregion
|
|
5534
|
+
//#region src/execute/io.ts
|
|
5535
|
+
const UTF8_ENCODER$2 = new TextEncoder();
|
|
5536
|
+
const NEWLINE = "\n";
|
|
5537
|
+
var EmptyInput = class {
|
|
5538
|
+
async *records() {}
|
|
5539
|
+
async *lines() {}
|
|
5540
|
+
async bytes() {
|
|
5541
|
+
return new Uint8Array();
|
|
5542
|
+
}
|
|
5543
|
+
};
|
|
5544
|
+
var RecordInput = class {
|
|
5545
|
+
input;
|
|
5546
|
+
constructor(input) {
|
|
5547
|
+
this.input = input;
|
|
5548
|
+
}
|
|
5549
|
+
records() {
|
|
5550
|
+
return this.input;
|
|
5551
|
+
}
|
|
5552
|
+
async *lines() {
|
|
5553
|
+
for await (const record of this.input) yield formatStdoutRecord(record);
|
|
5554
|
+
}
|
|
5555
|
+
async bytes(options = {}) {
|
|
5556
|
+
const lines = [];
|
|
5557
|
+
for await (const line of this.lines()) lines.push(line);
|
|
5558
|
+
if (lines.length === 0) return new Uint8Array();
|
|
5559
|
+
const text = options.trailingNewline ? `${lines.join(NEWLINE)}${NEWLINE}` : lines.join(NEWLINE);
|
|
5560
|
+
return UTF8_ENCODER$2.encode(text);
|
|
5561
|
+
}
|
|
5562
|
+
};
|
|
5563
|
+
var BufferedShellOutput = class {
|
|
5564
|
+
bufferedRecords = [];
|
|
5565
|
+
write(record) {
|
|
5566
|
+
this.bufferedRecords.push(record);
|
|
5567
|
+
}
|
|
5568
|
+
writeLine(text) {
|
|
5569
|
+
this.write({
|
|
5570
|
+
kind: "line",
|
|
5571
|
+
text
|
|
5572
|
+
});
|
|
5573
|
+
}
|
|
5574
|
+
records() {
|
|
5575
|
+
return [...this.bufferedRecords];
|
|
5576
|
+
}
|
|
5577
|
+
};
|
|
5578
|
+
function createShellInput(input) {
|
|
5579
|
+
return input ? new RecordInput(input) : new EmptyInput();
|
|
5580
|
+
}
|
|
5581
|
+
//#endregion
|
|
5221
5582
|
//#region src/operator/grep/grep.ts
|
|
5222
5583
|
const UTF8_DECODER$1 = new TextDecoder();
|
|
5223
5584
|
const UTF8_ENCODER$1 = new TextEncoder();
|
|
@@ -5280,7 +5641,12 @@ async function runGrepCommandInner(options) {
|
|
|
5280
5641
|
hadError ||= matcherBuild.compileError;
|
|
5281
5642
|
const searchTargets = await collectSearchTargets(normalized.fileOperands, parsed.options, options.fs, options.context);
|
|
5282
5643
|
hadError ||= searchTargets.hadError;
|
|
5283
|
-
const stdinBytes = normalized.readsFromStdin ? await readStdinBytes(
|
|
5644
|
+
const stdinBytes = normalized.readsFromStdin ? await readStdinBytes({
|
|
5645
|
+
fs: options.fs,
|
|
5646
|
+
input: options.input,
|
|
5647
|
+
inputRedirect: inputRedirectPath,
|
|
5648
|
+
stdin: options.stdin
|
|
5649
|
+
}) : null;
|
|
5284
5650
|
const displayFilename = shouldDisplayFilename(parsed.options, normalized.fileOperands);
|
|
5285
5651
|
const lines = [];
|
|
5286
5652
|
let anySelected = false;
|
|
@@ -5456,7 +5822,7 @@ async function collectSearchTargets(fileOperands, options, fs, context) {
|
|
|
5456
5822
|
const excludeMatchers = options.excludeFiles.map((pattern) => picomatch(pattern, { dot: true }));
|
|
5457
5823
|
const excludeDirMatchers = options.excludeDir.map((pattern) => picomatch(pattern, { dot: true }));
|
|
5458
5824
|
const shouldIncludeFile = (filePath) => {
|
|
5459
|
-
const name = basename$
|
|
5825
|
+
const name = basename$2(filePath);
|
|
5460
5826
|
if (excludeMatchers.some((matcher) => matcher(name))) return false;
|
|
5461
5827
|
if (includeMatchers.length > 0 && !includeMatchers.some((matcher) => matcher(name))) return false;
|
|
5462
5828
|
return true;
|
|
@@ -5472,7 +5838,7 @@ async function collectSearchTargets(fileOperands, options, fs, context) {
|
|
|
5472
5838
|
continue;
|
|
5473
5839
|
}
|
|
5474
5840
|
if (stat.isDirectory) {
|
|
5475
|
-
const childName = basename$
|
|
5841
|
+
const childName = basename$2(childPath);
|
|
5476
5842
|
if (excludeDirMatchers.some((matcher) => matcher(childName))) continue;
|
|
5477
5843
|
await walkDirectory(childPath, preferRelative);
|
|
5478
5844
|
continue;
|
|
@@ -5538,7 +5904,7 @@ function trimTrailingSlash$1(path) {
|
|
|
5538
5904
|
if (path === "/") return path;
|
|
5539
5905
|
return path.replace(/\/+$/g, "");
|
|
5540
5906
|
}
|
|
5541
|
-
function basename$
|
|
5907
|
+
function basename$2(path) {
|
|
5542
5908
|
const normalized = trimTrailingSlash$1(path);
|
|
5543
5909
|
const slashIndex = normalized.lastIndexOf("/");
|
|
5544
5910
|
if (slashIndex === -1) return normalized;
|
|
@@ -5551,17 +5917,15 @@ function toDisplayPath(path, cwd, preferRelative) {
|
|
|
5551
5917
|
if (!path.startsWith(prefix)) return path;
|
|
5552
5918
|
return path.slice(prefix.length);
|
|
5553
5919
|
}
|
|
5554
|
-
async function readStdinBytes(
|
|
5920
|
+
async function readStdinBytes(options) {
|
|
5921
|
+
const { fs, input, inputRedirect, stdin } = options;
|
|
5555
5922
|
if (inputRedirect !== null) try {
|
|
5556
5923
|
return await fs.readFile(inputRedirect);
|
|
5557
5924
|
} catch {
|
|
5558
5925
|
return new Uint8Array();
|
|
5559
5926
|
}
|
|
5560
5927
|
if (input === null) return new Uint8Array();
|
|
5561
|
-
|
|
5562
|
-
for await (const line of toLineStream(fs, input)) lines.push(line.text);
|
|
5563
|
-
if (lines.length === 0) return new Uint8Array();
|
|
5564
|
-
return UTF8_ENCODER$1.encode(`${lines.join("\n")}\n`);
|
|
5928
|
+
return await (stdin ?? createShellInput(input)).bytes({ trailingNewline: true });
|
|
5565
5929
|
}
|
|
5566
5930
|
function hasInputOutputConflict(fileOperands, readsFromStdin, cwd, inputRedirect, outputRedirect) {
|
|
5567
5931
|
if (outputRedirect === null) return false;
|
|
@@ -6182,7 +6546,7 @@ function headWithN(fs, n) {
|
|
|
6182
6546
|
}
|
|
6183
6547
|
//#endregion
|
|
6184
6548
|
//#region src/operator/ls/ls.ts
|
|
6185
|
-
function basename(path) {
|
|
6549
|
+
function basename$1(path) {
|
|
6186
6550
|
const normalized = path.replace(/\/+$/g, "");
|
|
6187
6551
|
const slashIndex = normalized.lastIndexOf("/");
|
|
6188
6552
|
if (slashIndex === -1) return normalized;
|
|
@@ -6198,7 +6562,7 @@ async function* ls(fs, path, options) {
|
|
|
6198
6562
|
return;
|
|
6199
6563
|
}
|
|
6200
6564
|
for await (const childPath of fs.readdir(path)) {
|
|
6201
|
-
if (!showAll && basename(childPath).startsWith(".")) continue;
|
|
6565
|
+
if (!showAll && basename$1(childPath).startsWith(".")) continue;
|
|
6202
6566
|
yield {
|
|
6203
6567
|
kind: "file",
|
|
6204
6568
|
path: childPath
|
|
@@ -6214,10 +6578,10 @@ function mkdir(fs) {
|
|
|
6214
6578
|
}
|
|
6215
6579
|
//#endregion
|
|
6216
6580
|
//#region src/operator/mv/mv.ts
|
|
6217
|
-
const TRAILING_SLASH_REGEX = /\/+$/;
|
|
6581
|
+
const TRAILING_SLASH_REGEX$1 = /\/+$/;
|
|
6218
6582
|
const MULTIPLE_SLASH_REGEX = /\/+/g;
|
|
6219
6583
|
function trimTrailingSlash(path) {
|
|
6220
|
-
return path.replace(TRAILING_SLASH_REGEX, "");
|
|
6584
|
+
return path.replace(TRAILING_SLASH_REGEX$1, "");
|
|
6221
6585
|
}
|
|
6222
6586
|
function extractFileName(path) {
|
|
6223
6587
|
const normalized = trimTrailingSlash(path);
|
|
@@ -6255,8 +6619,8 @@ function mv(fs) {
|
|
|
6255
6619
|
}
|
|
6256
6620
|
//#endregion
|
|
6257
6621
|
//#region src/operator/pwd/pwd.ts
|
|
6258
|
-
const ROOT_DIRECTORY$
|
|
6259
|
-
async function* pwd(cwd = ROOT_DIRECTORY$
|
|
6622
|
+
const ROOT_DIRECTORY$3 = "/";
|
|
6623
|
+
async function* pwd(cwd = ROOT_DIRECTORY$3) {
|
|
6260
6624
|
yield {
|
|
6261
6625
|
kind: "line",
|
|
6262
6626
|
text: cwd
|
|
@@ -6283,6 +6647,377 @@ function rm(fs) {
|
|
|
6283
6647
|
};
|
|
6284
6648
|
}
|
|
6285
6649
|
//#endregion
|
|
6650
|
+
//#region src/operator/sort/sort.ts
|
|
6651
|
+
const STDIN_FILE_NAME$1 = "-";
|
|
6652
|
+
const UTF8_ENCODER = new TextEncoder();
|
|
6653
|
+
async function runSortCommand(options) {
|
|
6654
|
+
if (options.parsed.diagnostics.length > 0) return {
|
|
6655
|
+
exitCode: 2,
|
|
6656
|
+
stderr: options.parsed.diagnostics.map((diagnostic) => `sort: ${diagnostic.message}`),
|
|
6657
|
+
stdout: []
|
|
6658
|
+
};
|
|
6659
|
+
const fileOperands = await evaluateExpandedPathWords("sort", options.parsed.files, options.fs, options.context);
|
|
6660
|
+
const stdinReader = createStdinLineReader(options);
|
|
6661
|
+
if (options.parsed.checkMode !== "none") return runCheckMode(options, fileOperands, stdinReader);
|
|
6662
|
+
const input = await collectSortInput(options, fileOperands, stdinReader);
|
|
6663
|
+
if (input.exitCode !== 0) return {
|
|
6664
|
+
exitCode: input.exitCode,
|
|
6665
|
+
stderr: input.stderr,
|
|
6666
|
+
stdout: []
|
|
6667
|
+
};
|
|
6668
|
+
const sortedLines = sortLines(input.lines, options.parsed);
|
|
6669
|
+
return {
|
|
6670
|
+
exitCode: 0,
|
|
6671
|
+
stderr: [],
|
|
6672
|
+
stdout: options.parsed.unique ? uniqueSortedLines(sortedLines, options.parsed) : sortedLines.map((line) => line.text)
|
|
6673
|
+
};
|
|
6674
|
+
}
|
|
6675
|
+
async function runCheckMode(options, fileOperands, stdinReader) {
|
|
6676
|
+
if (fileOperands.length > 1) return {
|
|
6677
|
+
exitCode: 2,
|
|
6678
|
+
stderr: [`sort: extra operand '${fileOperands[1] ?? ""}' not allowed with -${checkModeOption(options.parsed)}`],
|
|
6679
|
+
stdout: []
|
|
6680
|
+
};
|
|
6681
|
+
const fileOperand = fileOperands.at(0);
|
|
6682
|
+
if (fileOperand === STDIN_FILE_NAME$1) return checkStdinLines(stdinReader, options.parsed);
|
|
6683
|
+
if (fileOperand !== void 0) return checkPathLines(options.fs, resolvePathFromCwd(options.context.cwd, fileOperand), fileOperand, options.parsed);
|
|
6684
|
+
return checkStdinLines(stdinReader, options.parsed);
|
|
6685
|
+
}
|
|
6686
|
+
function checkModeOption(args) {
|
|
6687
|
+
return args.checkMode === "quiet" ? "C" : "c";
|
|
6688
|
+
}
|
|
6689
|
+
async function checkStdinLines(stdinReader, args) {
|
|
6690
|
+
try {
|
|
6691
|
+
return await checkSortedLines(stdinReader.read(), args);
|
|
6692
|
+
} catch {
|
|
6693
|
+
return createStdinCheckReadError(stdinReader.displayPath);
|
|
6694
|
+
}
|
|
6695
|
+
}
|
|
6696
|
+
async function checkPathLines(fs, path, displayPath, args) {
|
|
6697
|
+
try {
|
|
6698
|
+
return await checkSortedLines(fs.readLines(path), args);
|
|
6699
|
+
} catch {
|
|
6700
|
+
return {
|
|
6701
|
+
exitCode: 2,
|
|
6702
|
+
stderr: [`sort: cannot read: ${displayPath}: No such file or directory`],
|
|
6703
|
+
stdout: []
|
|
6704
|
+
};
|
|
6705
|
+
}
|
|
6706
|
+
}
|
|
6707
|
+
async function checkSortedLines(lines, args) {
|
|
6708
|
+
let previousLine = null;
|
|
6709
|
+
for await (const text of lines) {
|
|
6710
|
+
const currentLine = prepareSortLine(text, args);
|
|
6711
|
+
if (previousLine && !isSortedPair(previousLine, currentLine, args)) return {
|
|
6712
|
+
exitCode: 1,
|
|
6713
|
+
stderr: args.checkMode === "quiet" ? [] : [`sort: disorder: ${currentLine.text}`],
|
|
6714
|
+
stdout: []
|
|
6715
|
+
};
|
|
6716
|
+
previousLine = currentLine;
|
|
6717
|
+
}
|
|
6718
|
+
return {
|
|
6719
|
+
exitCode: 0,
|
|
6720
|
+
stderr: [],
|
|
6721
|
+
stdout: []
|
|
6722
|
+
};
|
|
6723
|
+
}
|
|
6724
|
+
function isSortedPair(previousLine, currentLine, args) {
|
|
6725
|
+
if (args.unique) return comparePrimary(previousLine, currentLine, args) < 0;
|
|
6726
|
+
return compareSortLines(previousLine, currentLine, args) <= 0;
|
|
6727
|
+
}
|
|
6728
|
+
async function collectSortInput(options, fileOperands, stdinReader) {
|
|
6729
|
+
if (fileOperands.length > 0) return collectFileOperandLines(options, fileOperands, stdinReader);
|
|
6730
|
+
return collectStdinLinesToArray(stdinReader);
|
|
6731
|
+
}
|
|
6732
|
+
async function collectFileOperandLines(options, fileOperands, stdinReader) {
|
|
6733
|
+
const lines = [];
|
|
6734
|
+
const stderr = [];
|
|
6735
|
+
for (const operand of fileOperands) {
|
|
6736
|
+
if (operand === STDIN_FILE_NAME$1) {
|
|
6737
|
+
const result = await collectStdinLinesToArray(stdinReader);
|
|
6738
|
+
if (result.exitCode !== 0) {
|
|
6739
|
+
stderr.push(...result.stderr);
|
|
6740
|
+
continue;
|
|
6741
|
+
}
|
|
6742
|
+
lines.push(...result.lines);
|
|
6743
|
+
continue;
|
|
6744
|
+
}
|
|
6745
|
+
const path = resolvePathFromCwd(options.context.cwd, operand);
|
|
6746
|
+
const result = await collectPathLines(options.fs, path, operand);
|
|
6747
|
+
if (result.exitCode !== 0) {
|
|
6748
|
+
stderr.push(...result.stderr);
|
|
6749
|
+
continue;
|
|
6750
|
+
}
|
|
6751
|
+
lines.push(...result.lines);
|
|
6752
|
+
}
|
|
6753
|
+
return {
|
|
6754
|
+
exitCode: stderr.length > 0 ? 2 : 0,
|
|
6755
|
+
lines: stderr.length > 0 ? [] : lines,
|
|
6756
|
+
stderr
|
|
6757
|
+
};
|
|
6758
|
+
}
|
|
6759
|
+
async function collectPathLines(fs, path, displayPath) {
|
|
6760
|
+
const lines = [];
|
|
6761
|
+
try {
|
|
6762
|
+
for await (const line of fs.readLines(path)) lines.push(line);
|
|
6763
|
+
} catch {
|
|
6764
|
+
return {
|
|
6765
|
+
exitCode: 2,
|
|
6766
|
+
lines: [],
|
|
6767
|
+
stderr: [`sort: cannot read: ${displayPath}: No such file or directory`]
|
|
6768
|
+
};
|
|
6769
|
+
}
|
|
6770
|
+
return {
|
|
6771
|
+
exitCode: 0,
|
|
6772
|
+
lines,
|
|
6773
|
+
stderr: []
|
|
6774
|
+
};
|
|
6775
|
+
}
|
|
6776
|
+
function createStdinLineReader(options) {
|
|
6777
|
+
let hasRead = false;
|
|
6778
|
+
return {
|
|
6779
|
+
displayPath: options.inputPath,
|
|
6780
|
+
read() {
|
|
6781
|
+
if (hasRead) return emptyLines();
|
|
6782
|
+
hasRead = true;
|
|
6783
|
+
if (options.inputPath) return options.fs.readLines(options.inputPath);
|
|
6784
|
+
return (options.stdin ?? createShellInput(options.input)).lines();
|
|
6785
|
+
}
|
|
6786
|
+
};
|
|
6787
|
+
}
|
|
6788
|
+
async function collectStdinLinesToArray(stdinReader) {
|
|
6789
|
+
const lines = [];
|
|
6790
|
+
try {
|
|
6791
|
+
for await (const line of stdinReader.read()) lines.push(line);
|
|
6792
|
+
} catch {
|
|
6793
|
+
return createStdinInputReadError(stdinReader.displayPath);
|
|
6794
|
+
}
|
|
6795
|
+
return {
|
|
6796
|
+
exitCode: 0,
|
|
6797
|
+
lines,
|
|
6798
|
+
stderr: []
|
|
6799
|
+
};
|
|
6800
|
+
}
|
|
6801
|
+
async function* emptyLines() {}
|
|
6802
|
+
function createStdinCheckReadError(path) {
|
|
6803
|
+
return {
|
|
6804
|
+
exitCode: 2,
|
|
6805
|
+
stderr: [createStdinReadErrorMessage(path)],
|
|
6806
|
+
stdout: []
|
|
6807
|
+
};
|
|
6808
|
+
}
|
|
6809
|
+
function createStdinInputReadError(path) {
|
|
6810
|
+
return {
|
|
6811
|
+
exitCode: 2,
|
|
6812
|
+
lines: [],
|
|
6813
|
+
stderr: [createStdinReadErrorMessage(path)]
|
|
6814
|
+
};
|
|
6815
|
+
}
|
|
6816
|
+
function createStdinReadErrorMessage(path) {
|
|
6817
|
+
return `sort: cannot read: ${path ?? STDIN_FILE_NAME$1}: No such file or directory`;
|
|
6818
|
+
}
|
|
6819
|
+
function sortLines(lines, args) {
|
|
6820
|
+
return lines.map((line) => prepareSortLine(line, args)).sort((left, right) => compareSortLines(left, right, args));
|
|
6821
|
+
}
|
|
6822
|
+
function uniqueSortedLines(lines, args) {
|
|
6823
|
+
const uniqueLines = [];
|
|
6824
|
+
let previous = null;
|
|
6825
|
+
for (const line of lines) {
|
|
6826
|
+
if (previous && comparePrimary(previous, line, args) === 0) continue;
|
|
6827
|
+
uniqueLines.push(line.text);
|
|
6828
|
+
previous = line;
|
|
6829
|
+
}
|
|
6830
|
+
return uniqueLines;
|
|
6831
|
+
}
|
|
6832
|
+
function prepareSortLine(text, args) {
|
|
6833
|
+
const value = createSortValue(text);
|
|
6834
|
+
return {
|
|
6835
|
+
keyValues: args.keys.map((key) => createSortValue(extractKey(text, key, args.fieldSeparator))),
|
|
6836
|
+
text,
|
|
6837
|
+
value
|
|
6838
|
+
};
|
|
6839
|
+
}
|
|
6840
|
+
function createSortValue(text) {
|
|
6841
|
+
return {
|
|
6842
|
+
bytes: UTF8_ENCODER.encode(text),
|
|
6843
|
+
numeric: parseNumericValue(text)
|
|
6844
|
+
};
|
|
6845
|
+
}
|
|
6846
|
+
function compareSortLines(left, right, args) {
|
|
6847
|
+
const primaryComparison = comparePrimary(left, right, args);
|
|
6848
|
+
if (primaryComparison !== 0) return primaryComparison;
|
|
6849
|
+
if (args.unique) return 0;
|
|
6850
|
+
return compareBytes(left.value.bytes, right.value.bytes);
|
|
6851
|
+
}
|
|
6852
|
+
function comparePrimary(left, right, args) {
|
|
6853
|
+
if (args.keys.length === 0) return compareValues(left.value, right.value, args.numeric);
|
|
6854
|
+
for (const [index, key] of args.keys.entries()) {
|
|
6855
|
+
const leftValue = left.keyValues[index];
|
|
6856
|
+
const rightValue = right.keyValues[index];
|
|
6857
|
+
if (!(leftValue && rightValue)) continue;
|
|
6858
|
+
const comparison = compareValues(leftValue, rightValue, args.numeric || key.options.numeric);
|
|
6859
|
+
if (comparison !== 0) return comparison;
|
|
6860
|
+
}
|
|
6861
|
+
return 0;
|
|
6862
|
+
}
|
|
6863
|
+
function compareValues(left, right, numeric) {
|
|
6864
|
+
if (numeric) return compareNumericValues(left.numeric, right.numeric);
|
|
6865
|
+
return compareBytes(left.bytes, right.bytes);
|
|
6866
|
+
}
|
|
6867
|
+
function compareNumericValues(left, right) {
|
|
6868
|
+
if (left.sign !== right.sign) return left.sign - right.sign;
|
|
6869
|
+
if (left.sign === 0) return 0;
|
|
6870
|
+
const magnitudeComparison = compareNumericMagnitude(left, right);
|
|
6871
|
+
return left.sign > 0 ? magnitudeComparison : -magnitudeComparison;
|
|
6872
|
+
}
|
|
6873
|
+
function compareNumericMagnitude(left, right) {
|
|
6874
|
+
if (left.integer.length !== right.integer.length) return left.integer.length - right.integer.length;
|
|
6875
|
+
const integerComparison = compareAsciiDigits(left.integer, right.integer);
|
|
6876
|
+
if (integerComparison !== 0) return integerComparison;
|
|
6877
|
+
const maxFractionLength = Math.max(left.fraction.length, right.fraction.length);
|
|
6878
|
+
for (let index = 0; index < maxFractionLength; index += 1) {
|
|
6879
|
+
const leftDigit = digitValue(left.fraction.at(index));
|
|
6880
|
+
const rightDigit = digitValue(right.fraction.at(index));
|
|
6881
|
+
if (leftDigit !== rightDigit) return leftDigit - rightDigit;
|
|
6882
|
+
}
|
|
6883
|
+
return 0;
|
|
6884
|
+
}
|
|
6885
|
+
function compareAsciiDigits(left, right) {
|
|
6886
|
+
for (let index = 0; index < left.length; index += 1) {
|
|
6887
|
+
const difference = digitValue(left.at(index)) - digitValue(right.at(index));
|
|
6888
|
+
if (difference !== 0) return difference;
|
|
6889
|
+
}
|
|
6890
|
+
return 0;
|
|
6891
|
+
}
|
|
6892
|
+
function parseNumericValue(value) {
|
|
6893
|
+
let index = skipLeadingBlanks(value);
|
|
6894
|
+
let sign = 1;
|
|
6895
|
+
if (value.at(index) === "-") {
|
|
6896
|
+
sign = -1;
|
|
6897
|
+
index += 1;
|
|
6898
|
+
}
|
|
6899
|
+
const integerStart = index;
|
|
6900
|
+
while (isAsciiDigit(value.at(index))) index += 1;
|
|
6901
|
+
const integer = value.slice(integerStart, index);
|
|
6902
|
+
let fraction = "";
|
|
6903
|
+
if (value.at(index) === ".") {
|
|
6904
|
+
index += 1;
|
|
6905
|
+
const fractionStart = index;
|
|
6906
|
+
while (isAsciiDigit(value.at(index))) index += 1;
|
|
6907
|
+
fraction = value.slice(fractionStart, index);
|
|
6908
|
+
}
|
|
6909
|
+
if (integer === "" && fraction === "") return createZeroNumericValue();
|
|
6910
|
+
const normalizedInteger = integer.replace(/^0+/g, "");
|
|
6911
|
+
const normalizedFraction = fraction.replace(/0+$/g, "");
|
|
6912
|
+
if (normalizedInteger === "" && normalizedFraction === "") return createZeroNumericValue();
|
|
6913
|
+
return {
|
|
6914
|
+
fraction: normalizedFraction,
|
|
6915
|
+
integer: normalizedInteger,
|
|
6916
|
+
sign
|
|
6917
|
+
};
|
|
6918
|
+
}
|
|
6919
|
+
function createZeroNumericValue() {
|
|
6920
|
+
return {
|
|
6921
|
+
fraction: "",
|
|
6922
|
+
integer: "",
|
|
6923
|
+
sign: 0
|
|
6924
|
+
};
|
|
6925
|
+
}
|
|
6926
|
+
function skipLeadingBlanks(value) {
|
|
6927
|
+
let index = 0;
|
|
6928
|
+
while (isBlank(value.at(index))) index += 1;
|
|
6929
|
+
return index;
|
|
6930
|
+
}
|
|
6931
|
+
function isAsciiDigit(character) {
|
|
6932
|
+
return character !== void 0 && character >= "0" && character <= "9";
|
|
6933
|
+
}
|
|
6934
|
+
function digitValue(character) {
|
|
6935
|
+
return character === void 0 ? 0 : character.charCodeAt(0) - 48;
|
|
6936
|
+
}
|
|
6937
|
+
function compareBytes(left, right) {
|
|
6938
|
+
const length = Math.min(left.byteLength, right.byteLength);
|
|
6939
|
+
for (let index = 0; index < length; index += 1) {
|
|
6940
|
+
const difference = (left[index] ?? 0) - (right[index] ?? 0);
|
|
6941
|
+
if (difference !== 0) return difference;
|
|
6942
|
+
}
|
|
6943
|
+
return left.byteLength - right.byteLength;
|
|
6944
|
+
}
|
|
6945
|
+
function extractKey(line, key, fieldSeparator) {
|
|
6946
|
+
const layout = createFieldLayout(line, fieldSeparator);
|
|
6947
|
+
const start = keyPositionToStartIndex(line, layout, key.start);
|
|
6948
|
+
const end = key.end ? keyPositionToEndIndex(line, layout, key.end) : line.length;
|
|
6949
|
+
if (end < start) return "";
|
|
6950
|
+
return line.slice(start, end);
|
|
6951
|
+
}
|
|
6952
|
+
function keyPositionToStartIndex(line, layout, position) {
|
|
6953
|
+
const fieldStart = fieldStartIndex(layout, position.field, line.length);
|
|
6954
|
+
if (position.character === null) return fieldStart;
|
|
6955
|
+
return Math.min(fieldStart + position.character - 1, line.length);
|
|
6956
|
+
}
|
|
6957
|
+
function keyPositionToEndIndex(line, layout, position) {
|
|
6958
|
+
const fieldStart = fieldStartIndex(layout, position.field, line.length);
|
|
6959
|
+
if (position.character === null || position.character === 0) return fieldEndIndex(layout, position.field, line.length);
|
|
6960
|
+
return Math.min(fieldStart + position.character, line.length);
|
|
6961
|
+
}
|
|
6962
|
+
function createFieldLayout(line, fieldSeparator) {
|
|
6963
|
+
if (fieldSeparator !== null) return createSeparatedFieldLayout(line, fieldSeparator);
|
|
6964
|
+
return createBlankDelimitedFieldLayout(line);
|
|
6965
|
+
}
|
|
6966
|
+
function createSeparatedFieldLayout(line, fieldSeparator) {
|
|
6967
|
+
if (fieldSeparator === "") return {
|
|
6968
|
+
ends: [line.length],
|
|
6969
|
+
starts: [0]
|
|
6970
|
+
};
|
|
6971
|
+
const starts = [0];
|
|
6972
|
+
const ends = [];
|
|
6973
|
+
let index = 0;
|
|
6974
|
+
while (index < line.length) {
|
|
6975
|
+
if (!line.startsWith(fieldSeparator, index)) {
|
|
6976
|
+
index += 1;
|
|
6977
|
+
continue;
|
|
6978
|
+
}
|
|
6979
|
+
ends.push(index);
|
|
6980
|
+
index += fieldSeparator.length;
|
|
6981
|
+
starts.push(index);
|
|
6982
|
+
}
|
|
6983
|
+
ends.push(line.length);
|
|
6984
|
+
return {
|
|
6985
|
+
ends,
|
|
6986
|
+
starts
|
|
6987
|
+
};
|
|
6988
|
+
}
|
|
6989
|
+
function createBlankDelimitedFieldLayout(line) {
|
|
6990
|
+
const starts = [0];
|
|
6991
|
+
const ends = [];
|
|
6992
|
+
let index = 0;
|
|
6993
|
+
while (index < line.length) {
|
|
6994
|
+
if (!isBlank(line.at(index))) {
|
|
6995
|
+
index += 1;
|
|
6996
|
+
continue;
|
|
6997
|
+
}
|
|
6998
|
+
const blankStart = index;
|
|
6999
|
+
while (index < line.length && isBlank(line.at(index))) index += 1;
|
|
7000
|
+
if (blankStart === 0) continue;
|
|
7001
|
+
if (index >= line.length) continue;
|
|
7002
|
+
ends.push(blankStart);
|
|
7003
|
+
starts.push(blankStart);
|
|
7004
|
+
}
|
|
7005
|
+
while (ends.length < starts.length) ends.push(line.length);
|
|
7006
|
+
return {
|
|
7007
|
+
ends,
|
|
7008
|
+
starts
|
|
7009
|
+
};
|
|
7010
|
+
}
|
|
7011
|
+
function isBlank(character) {
|
|
7012
|
+
return character === " " || character === " ";
|
|
7013
|
+
}
|
|
7014
|
+
function fieldStartIndex(layout, field, lineLength) {
|
|
7015
|
+
return layout.starts[field - 1] ?? lineLength;
|
|
7016
|
+
}
|
|
7017
|
+
function fieldEndIndex(layout, field, lineLength) {
|
|
7018
|
+
return layout.ends[field - 1] ?? lineLength;
|
|
7019
|
+
}
|
|
7020
|
+
//#endregion
|
|
6286
7021
|
//#region src/operator/tail/tail.ts
|
|
6287
7022
|
function tail(n) {
|
|
6288
7023
|
return async function* (input) {
|
|
@@ -6312,9 +7047,205 @@ function touch(fs) {
|
|
|
6312
7047
|
};
|
|
6313
7048
|
}
|
|
6314
7049
|
//#endregion
|
|
7050
|
+
//#region src/operator/tree/tree.ts
|
|
7051
|
+
const ROOT_DIRECTORY$2 = "/";
|
|
7052
|
+
const TRAILING_SLASH_REGEX = /\/+$/;
|
|
7053
|
+
const LINE_DRAWING = {
|
|
7054
|
+
ascii: {
|
|
7055
|
+
blank: " ",
|
|
7056
|
+
last: "`-- ",
|
|
7057
|
+
mid: "|-- ",
|
|
7058
|
+
pipe: "| "
|
|
7059
|
+
},
|
|
7060
|
+
utf8: {
|
|
7061
|
+
blank: " ",
|
|
7062
|
+
last: "└── ",
|
|
7063
|
+
mid: "├── ",
|
|
7064
|
+
pipe: "│ "
|
|
7065
|
+
}
|
|
7066
|
+
};
|
|
7067
|
+
async function runTreeCommand(fs, cwd, args) {
|
|
7068
|
+
const stdout = [];
|
|
7069
|
+
const stderr = [];
|
|
7070
|
+
const totals = {
|
|
7071
|
+
dirs: 0,
|
|
7072
|
+
files: 0
|
|
7073
|
+
};
|
|
7074
|
+
let exitCode = 0;
|
|
7075
|
+
for (const path of args.paths) {
|
|
7076
|
+
const resolvedPath = resolvePathFromCwd(cwd, path);
|
|
7077
|
+
let stat;
|
|
7078
|
+
try {
|
|
7079
|
+
stat = await fs.stat(resolvedPath);
|
|
7080
|
+
} catch {
|
|
7081
|
+
stderr.push(`tree: ${path}: No such file or directory`);
|
|
7082
|
+
exitCode = 1;
|
|
7083
|
+
continue;
|
|
7084
|
+
}
|
|
7085
|
+
const rootEntry = await buildTreeEntry({
|
|
7086
|
+
args,
|
|
7087
|
+
depth: 0,
|
|
7088
|
+
forceIncludeAll: false,
|
|
7089
|
+
fs,
|
|
7090
|
+
isDirectory: stat.isDirectory,
|
|
7091
|
+
path: resolvedPath,
|
|
7092
|
+
rootDisplayPath: path
|
|
7093
|
+
});
|
|
7094
|
+
if (!rootEntry) continue;
|
|
7095
|
+
appendRenderedTree(stdout, rootEntry, args);
|
|
7096
|
+
accumulateTotals(rootEntry, totals);
|
|
7097
|
+
}
|
|
7098
|
+
if (!args.noReport) appendReport(stdout, totals, args);
|
|
7099
|
+
return {
|
|
7100
|
+
exitCode,
|
|
7101
|
+
stderr,
|
|
7102
|
+
stdout
|
|
7103
|
+
};
|
|
7104
|
+
}
|
|
7105
|
+
function createTreeResolvedArgs(args) {
|
|
7106
|
+
return {
|
|
7107
|
+
...args,
|
|
7108
|
+
excludePatterns: createPatternSet(args.excludePatterns),
|
|
7109
|
+
includePatterns: createPatternSet(args.includePatterns)
|
|
7110
|
+
};
|
|
7111
|
+
}
|
|
7112
|
+
async function buildTreeEntry({ args, depth, forceIncludeAll, fs, isDirectory, path, rootDisplayPath }) {
|
|
7113
|
+
const name = basename(path);
|
|
7114
|
+
const isRoot = depth === 0;
|
|
7115
|
+
const displayName = isRoot ? formatRootDisplayName(rootDisplayPath, path, args) : formatChildDisplayName(path, isDirectory, args);
|
|
7116
|
+
if (!isRoot && shouldHide(name, args)) return null;
|
|
7117
|
+
if (!isRoot && matchesPattern(args.excludePatterns, name, path)) return null;
|
|
7118
|
+
if (!isRoot && args.dirsOnly && !isDirectory) return null;
|
|
7119
|
+
if (!isDirectory) {
|
|
7120
|
+
if (!forceIncludeAll && args.includePatterns.matchers.length > 0 && !matchesPattern(args.includePatterns, name, path)) return null;
|
|
7121
|
+
return {
|
|
7122
|
+
children: [],
|
|
7123
|
+
displayName,
|
|
7124
|
+
isDirectory,
|
|
7125
|
+
path
|
|
7126
|
+
};
|
|
7127
|
+
}
|
|
7128
|
+
const dirMatchesInclude = !isRoot && args.matchDirs && matchesPattern(args.includePatterns, name, path);
|
|
7129
|
+
const childForceIncludeAll = forceIncludeAll || dirMatchesInclude;
|
|
7130
|
+
const children = canDescend(depth, args) && isDirectory ? await buildChildEntries({
|
|
7131
|
+
args,
|
|
7132
|
+
depth,
|
|
7133
|
+
forceIncludeAll: childForceIncludeAll,
|
|
7134
|
+
fs,
|
|
7135
|
+
path
|
|
7136
|
+
}) : [];
|
|
7137
|
+
if (!isRoot && args.prune && !dirMatchesInclude && children.length === 0) return null;
|
|
7138
|
+
return {
|
|
7139
|
+
children,
|
|
7140
|
+
displayName,
|
|
7141
|
+
isDirectory,
|
|
7142
|
+
path
|
|
7143
|
+
};
|
|
7144
|
+
}
|
|
7145
|
+
async function buildChildEntries({ args, depth, forceIncludeAll, fs, path }) {
|
|
7146
|
+
const childPaths = await readSortedChildren(fs, path);
|
|
7147
|
+
const entries = [];
|
|
7148
|
+
for (const childPath of childPaths) {
|
|
7149
|
+
const childDepth = depth + 1;
|
|
7150
|
+
if (args.maxDepth !== null && childDepth > args.maxDepth) continue;
|
|
7151
|
+
const childEntry = await buildTreeEntry({
|
|
7152
|
+
args,
|
|
7153
|
+
depth: childDepth,
|
|
7154
|
+
forceIncludeAll,
|
|
7155
|
+
fs,
|
|
7156
|
+
isDirectory: (await fs.stat(childPath)).isDirectory,
|
|
7157
|
+
path: childPath,
|
|
7158
|
+
rootDisplayPath: childPath
|
|
7159
|
+
});
|
|
7160
|
+
if (childEntry) entries.push(childEntry);
|
|
7161
|
+
}
|
|
7162
|
+
return entries;
|
|
7163
|
+
}
|
|
7164
|
+
async function readSortedChildren(fs, path) {
|
|
7165
|
+
const children = [];
|
|
7166
|
+
for await (const childPath of fs.readdir(path)) children.push(childPath);
|
|
7167
|
+
children.sort((left, right) => basename(left).localeCompare(basename(right)));
|
|
7168
|
+
return children;
|
|
7169
|
+
}
|
|
7170
|
+
function appendRenderedTree(stdout, rootEntry, args) {
|
|
7171
|
+
stdout.push(rootEntry.displayName);
|
|
7172
|
+
const drawing = args.ascii ? LINE_DRAWING.ascii : LINE_DRAWING.utf8;
|
|
7173
|
+
for (const [index, child] of rootEntry.children.entries()) appendRenderedEntry({
|
|
7174
|
+
drawing,
|
|
7175
|
+
entry: child,
|
|
7176
|
+
isLast: index === rootEntry.children.length - 1,
|
|
7177
|
+
prefix: "",
|
|
7178
|
+
stdout
|
|
7179
|
+
});
|
|
7180
|
+
}
|
|
7181
|
+
function appendRenderedEntry({ drawing, entry, isLast, prefix, stdout }) {
|
|
7182
|
+
stdout.push(`${prefix}${isLast ? drawing.last : drawing.mid}${entry.displayName}`);
|
|
7183
|
+
const childPrefix = `${prefix}${isLast ? drawing.blank : drawing.pipe}`;
|
|
7184
|
+
for (const [index, child] of entry.children.entries()) appendRenderedEntry({
|
|
7185
|
+
drawing,
|
|
7186
|
+
entry: child,
|
|
7187
|
+
isLast: index === entry.children.length - 1,
|
|
7188
|
+
prefix: childPrefix,
|
|
7189
|
+
stdout
|
|
7190
|
+
});
|
|
7191
|
+
}
|
|
7192
|
+
function appendReport(stdout, totals, args) {
|
|
7193
|
+
stdout.push("");
|
|
7194
|
+
if (args.dirsOnly) {
|
|
7195
|
+
stdout.push(`${totals.dirs} ${totals.dirs === 1 ? "directory" : "directories"}`);
|
|
7196
|
+
return;
|
|
7197
|
+
}
|
|
7198
|
+
stdout.push(`${totals.dirs} ${totals.dirs === 1 ? "directory" : "directories"}, ${totals.files} ${totals.files === 1 ? "file" : "files"}`);
|
|
7199
|
+
}
|
|
7200
|
+
function accumulateTotals(entry, totals) {
|
|
7201
|
+
if (entry.isDirectory) totals.dirs += 1;
|
|
7202
|
+
else totals.files += 1;
|
|
7203
|
+
for (const child of entry.children) accumulateTotals(child, totals);
|
|
7204
|
+
}
|
|
7205
|
+
function createPatternSet(patterns) {
|
|
7206
|
+
return { matchers: patterns.flatMap(splitAlternatePatterns).map((pattern) => picomatch(pattern, {
|
|
7207
|
+
bash: true,
|
|
7208
|
+
dot: true
|
|
7209
|
+
})) };
|
|
7210
|
+
}
|
|
7211
|
+
function splitAlternatePatterns(pattern) {
|
|
7212
|
+
return pattern.split("|").map((part) => part.trim()).filter((part) => part.length > 0);
|
|
7213
|
+
}
|
|
7214
|
+
function matchesPattern(patterns, name, path) {
|
|
7215
|
+
if (patterns.matchers.length === 0) return false;
|
|
7216
|
+
const normalizedPath = normalizeAbsolutePath(path);
|
|
7217
|
+
const relativePath = normalizedPath.startsWith(ROOT_DIRECTORY$2) ? normalizedPath.slice(1) : normalizedPath;
|
|
7218
|
+
return patterns.matchers.some((matcher) => matcher(name) || matcher(relativePath));
|
|
7219
|
+
}
|
|
7220
|
+
function shouldHide(name, args) {
|
|
7221
|
+
return !args.showAll && name.startsWith(".");
|
|
7222
|
+
}
|
|
7223
|
+
function canDescend(depth, args) {
|
|
7224
|
+
return args.maxDepth === null || depth < args.maxDepth;
|
|
7225
|
+
}
|
|
7226
|
+
function formatRootDisplayName(displayPath, resolvedPath, args) {
|
|
7227
|
+
const rootName = args.fullPath ? resolvedPath : displayPath;
|
|
7228
|
+
if (args.classify) return withDirectorySlash(rootName);
|
|
7229
|
+
return rootName;
|
|
7230
|
+
}
|
|
7231
|
+
function formatChildDisplayName(path, isDirectory, args) {
|
|
7232
|
+
const displayName = args.fullPath ? path : basename(path);
|
|
7233
|
+
if (args.classify && isDirectory) return withDirectorySlash(displayName);
|
|
7234
|
+
return displayName;
|
|
7235
|
+
}
|
|
7236
|
+
function withDirectorySlash(path) {
|
|
7237
|
+
if (path === ROOT_DIRECTORY$2 || path.endsWith(ROOT_DIRECTORY$2)) return path;
|
|
7238
|
+
return `${path}/`;
|
|
7239
|
+
}
|
|
7240
|
+
function basename(path) {
|
|
7241
|
+
const normalized = path.replace(TRAILING_SLASH_REGEX, "");
|
|
7242
|
+
const slashIndex = normalized.lastIndexOf(ROOT_DIRECTORY$2);
|
|
7243
|
+
if (slashIndex === -1) return normalized;
|
|
7244
|
+
return normalized.slice(slashIndex + 1);
|
|
7245
|
+
}
|
|
7246
|
+
//#endregion
|
|
6315
7247
|
//#region src/operator/wc/wc.ts
|
|
6316
7248
|
const UTF8_DECODER = new TextDecoder();
|
|
6317
|
-
const UTF8_ENCODER = new TextEncoder();
|
|
6318
7249
|
const DEFAULT_STDIN_DISPLAY_PATH = null;
|
|
6319
7250
|
const DEFAULT_STDIO_BYTES = new Uint8Array();
|
|
6320
7251
|
const STDIN_FILE_NAME = "-";
|
|
@@ -6410,7 +7341,7 @@ async function runWcCommand(options) {
|
|
|
6410
7341
|
stderr,
|
|
6411
7342
|
stdout: []
|
|
6412
7343
|
};
|
|
6413
|
-
const readStdinBytes = createStdinReader(options.input, redirectedInputBytes);
|
|
7344
|
+
const readStdinBytes = createStdinReader(options.input, redirectedInputBytes, options.stdin);
|
|
6414
7345
|
const fileOperands = await evaluateExpandedPathWords("wc", options.parsed.files, options.fs, options.context);
|
|
6415
7346
|
if (options.parsed.files0From && fileOperands.length > 0) return {
|
|
6416
7347
|
exitCode: 1,
|
|
@@ -6544,19 +7475,17 @@ async function readFileOrReport(fs, path, stderr) {
|
|
|
6544
7475
|
return null;
|
|
6545
7476
|
}
|
|
6546
7477
|
}
|
|
6547
|
-
function createStdinReader(input, redirectedInputBytes) {
|
|
7478
|
+
function createStdinReader(input, redirectedInputBytes, stdin) {
|
|
6548
7479
|
let hasRead = false;
|
|
6549
7480
|
return async () => {
|
|
6550
7481
|
if (hasRead) return DEFAULT_STDIO_BYTES;
|
|
6551
7482
|
hasRead = true;
|
|
6552
|
-
return redirectedInputBytes ?? readStreamBytes(input);
|
|
7483
|
+
return redirectedInputBytes ?? readStreamBytes(input, stdin);
|
|
6553
7484
|
};
|
|
6554
7485
|
}
|
|
6555
|
-
async function readStreamBytes(input) {
|
|
7486
|
+
async function readStreamBytes(input, stdin) {
|
|
6556
7487
|
if (!input) return DEFAULT_STDIO_BYTES;
|
|
6557
|
-
|
|
6558
|
-
for await (const record of input) textParts.push(formatRecord(record));
|
|
6559
|
-
return UTF8_ENCODER.encode(textParts.join("\n"));
|
|
7488
|
+
return await (stdin ?? createShellInput(input)).bytes({ trailingNewline: true });
|
|
6560
7489
|
}
|
|
6561
7490
|
function countBytes(bytes) {
|
|
6562
7491
|
const text = UTF8_DECODER.decode(bytes);
|
|
@@ -6743,7 +7672,7 @@ async function readInput(options) {
|
|
|
6743
7672
|
if (options.inputPath) return TEXT_DECODER.decode(await options.fs.readFile(options.inputPath));
|
|
6744
7673
|
if (!options.input) return "";
|
|
6745
7674
|
const records = [];
|
|
6746
|
-
for await (const
|
|
7675
|
+
for await (const line of (options.stdin ?? createShellInput(options.input)).lines()) records.push(line);
|
|
6747
7676
|
return records.join("\n");
|
|
6748
7677
|
}
|
|
6749
7678
|
function buildBatches(input, args) {
|
|
@@ -6932,9 +7861,11 @@ const STREAM_COMMANDS = [
|
|
|
6932
7861
|
"pwd",
|
|
6933
7862
|
"read",
|
|
6934
7863
|
"set",
|
|
7864
|
+
"sort",
|
|
6935
7865
|
"string",
|
|
6936
7866
|
"tail",
|
|
6937
7867
|
"test",
|
|
7868
|
+
"tree",
|
|
6938
7869
|
"xargs",
|
|
6939
7870
|
"wc"
|
|
6940
7871
|
];
|
|
@@ -6986,10 +7917,17 @@ async function executeEffectStep$1({ step, fs, context }) {
|
|
|
6986
7917
|
});
|
|
6987
7918
|
}
|
|
6988
7919
|
function createBuiltinRuntime(fs, context, input) {
|
|
7920
|
+
const stdin = createShellInput(input);
|
|
6989
7921
|
return {
|
|
6990
7922
|
fs,
|
|
6991
7923
|
context,
|
|
6992
|
-
input
|
|
7924
|
+
input,
|
|
7925
|
+
io: {
|
|
7926
|
+
stderr: context.stderr,
|
|
7927
|
+
stdin,
|
|
7928
|
+
stdout: new BufferedShellOutput()
|
|
7929
|
+
},
|
|
7930
|
+
stdin
|
|
6993
7931
|
};
|
|
6994
7932
|
}
|
|
6995
7933
|
function formatLongListing(path, stat) {
|
|
@@ -7055,7 +7993,7 @@ CommandRegistry.register("cat", {
|
|
|
7055
7993
|
context.status = 0;
|
|
7056
7994
|
return;
|
|
7057
7995
|
}
|
|
7058
|
-
if (input) yield* cat(fs, options)(input);
|
|
7996
|
+
if (input) yield* cat(fs, options)(toFormattedLineStream(input));
|
|
7059
7997
|
context.status = 0;
|
|
7060
7998
|
})();
|
|
7061
7999
|
}
|
|
@@ -7070,7 +8008,8 @@ CommandRegistry.register("grep", {
|
|
|
7070
8008
|
input,
|
|
7071
8009
|
parsed: step.args,
|
|
7072
8010
|
redirections: step.redirections,
|
|
7073
|
-
resolvedOutputRedirectPath
|
|
8011
|
+
resolvedOutputRedirectPath,
|
|
8012
|
+
stdin: createShellInput(input)
|
|
7074
8013
|
});
|
|
7075
8014
|
context.status = result.exitCode;
|
|
7076
8015
|
context.stderr.appendLines(result.stderr);
|
|
@@ -7096,7 +8035,8 @@ CommandRegistry.register("xargs", {
|
|
|
7096
8035
|
fs,
|
|
7097
8036
|
input,
|
|
7098
8037
|
inputPath: await resolveRedirectPath(step.cmd, step.redirections, "input", fs, context),
|
|
7099
|
-
parsed: step.args
|
|
8038
|
+
parsed: step.args,
|
|
8039
|
+
stdin: createShellInput(input)
|
|
7100
8040
|
});
|
|
7101
8041
|
context.status = result.exitCode;
|
|
7102
8042
|
context.stderr.appendLines(result.stderr);
|
|
@@ -7116,7 +8056,8 @@ CommandRegistry.register("wc", {
|
|
|
7116
8056
|
fs,
|
|
7117
8057
|
input,
|
|
7118
8058
|
inputPath: await resolveRedirectPath(step.cmd, step.redirections, "input", fs, context),
|
|
7119
|
-
parsed: step.args
|
|
8059
|
+
parsed: step.args,
|
|
8060
|
+
stdin: createShellInput(input)
|
|
7120
8061
|
});
|
|
7121
8062
|
context.status = result.exitCode;
|
|
7122
8063
|
context.stderr.appendLines(result.stderr);
|
|
@@ -7127,6 +8068,49 @@ CommandRegistry.register("wc", {
|
|
|
7127
8068
|
})();
|
|
7128
8069
|
}
|
|
7129
8070
|
});
|
|
8071
|
+
CommandRegistry.register("sort", {
|
|
8072
|
+
kind: "stream",
|
|
8073
|
+
handler: ({ step, fs, input, context }) => {
|
|
8074
|
+
return (async function* () {
|
|
8075
|
+
const result = await runSortCommand({
|
|
8076
|
+
context,
|
|
8077
|
+
fs,
|
|
8078
|
+
input,
|
|
8079
|
+
inputPath: await resolveRedirectPath(step.cmd, step.redirections, "input", fs, context),
|
|
8080
|
+
parsed: step.args,
|
|
8081
|
+
stdin: createShellInput(input)
|
|
8082
|
+
});
|
|
8083
|
+
context.status = result.exitCode;
|
|
8084
|
+
context.stderr.appendLines(result.stderr);
|
|
8085
|
+
for (const text of result.stdout) yield {
|
|
8086
|
+
kind: "line",
|
|
8087
|
+
text
|
|
8088
|
+
};
|
|
8089
|
+
})();
|
|
8090
|
+
}
|
|
8091
|
+
});
|
|
8092
|
+
CommandRegistry.register("tree", {
|
|
8093
|
+
kind: "stream",
|
|
8094
|
+
handler: ({ step, fs, context }) => {
|
|
8095
|
+
return (async function* () {
|
|
8096
|
+
const paths = resolvePathsFromCwd(context.cwd, await evaluateExpandedPathWords("tree", step.args.paths, fs, context));
|
|
8097
|
+
const includePatterns = await evaluateExpandedWords(step.args.includePatterns, fs, context);
|
|
8098
|
+
const excludePatterns = await evaluateExpandedWords(step.args.excludePatterns, fs, context);
|
|
8099
|
+
const result = await runTreeCommand(fs, context.cwd, createTreeResolvedArgs({
|
|
8100
|
+
...step.args,
|
|
8101
|
+
excludePatterns,
|
|
8102
|
+
includePatterns,
|
|
8103
|
+
paths
|
|
8104
|
+
}));
|
|
8105
|
+
context.status = result.exitCode;
|
|
8106
|
+
context.stderr.appendLines(result.stderr);
|
|
8107
|
+
for (const text of result.stdout) yield {
|
|
8108
|
+
kind: "line",
|
|
8109
|
+
text
|
|
8110
|
+
};
|
|
8111
|
+
})();
|
|
8112
|
+
}
|
|
8113
|
+
});
|
|
7130
8114
|
CommandRegistry.register("head", {
|
|
7131
8115
|
kind: "stream",
|
|
7132
8116
|
handler: ({ step, fs, input, context }) => {
|
|
@@ -7511,11 +8495,13 @@ function getTargetFd(redirection) {
|
|
|
7511
8495
|
}
|
|
7512
8496
|
async function resolveFileDestination(command, redirection, fs, context) {
|
|
7513
8497
|
const targetPath = await evaluateExpandedSinglePath(command, "redirection target must expand to exactly 1 path", redirection.target, fs, context);
|
|
8498
|
+
const resolvedPath = resolvePathFromCwd(context.cwd, targetPath);
|
|
8499
|
+
if (isNullDevicePath(resolvedPath)) return { kind: "nullDevice" };
|
|
7514
8500
|
return {
|
|
7515
8501
|
kind: "file",
|
|
7516
8502
|
append: redirection.append ?? false,
|
|
7517
8503
|
noclobber: redirection.noclobber ?? false,
|
|
7518
|
-
path:
|
|
8504
|
+
path: resolvedPath
|
|
7519
8505
|
};
|
|
7520
8506
|
}
|
|
7521
8507
|
function destinationForFd(routing, fd, _isLastStep) {
|
|
@@ -7675,6 +8661,7 @@ async function routeStdout(stdoutRecords, stdoutText, destination, hasNextStep,
|
|
|
7675
8661
|
});
|
|
7676
8662
|
return;
|
|
7677
8663
|
case "closed": return;
|
|
8664
|
+
case "nullDevice": return;
|
|
7678
8665
|
default: {
|
|
7679
8666
|
const _exhaustive = destination;
|
|
7680
8667
|
throw new Error(`Unknown stdout destination: ${_exhaustive}`);
|
|
@@ -7707,6 +8694,7 @@ async function routeStderr(stderrLines, stderrText, destination, hasNextStep, pi
|
|
|
7707
8694
|
});
|
|
7708
8695
|
return;
|
|
7709
8696
|
case "closed": return;
|
|
8697
|
+
case "nullDevice": return;
|
|
7710
8698
|
default: {
|
|
7711
8699
|
const _exhaustive = destination;
|
|
7712
8700
|
throw new Error(`Unknown stderr destination: ${_exhaustive}`);
|
|
@@ -7716,4 +8704,4 @@ async function routeStderr(stderrLines, stderrText, destination, hasNextStep, pi
|
|
|
7716
8704
|
//#endregion
|
|
7717
8705
|
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 };
|
|
7718
8706
|
|
|
7719
|
-
//# sourceMappingURL=execute-
|
|
8707
|
+
//# sourceMappingURL=execute-BinccNiS.mjs.map
|