(text: string, maxLines: number, maxBytes: number)
| 223 | } |
| 224 | |
| 225 | function tail(text: string, maxLines: number, maxBytes: number) { |
| 226 | const lines = text.split("\n") |
| 227 | if (lines.length <= maxLines && Buffer.byteLength(text, "utf-8") <= maxBytes) { |
| 228 | return { |
| 229 | text, |
| 230 | cut: false, |
| 231 | } |
| 232 | } |
| 233 | |
| 234 | const out: string[] = [] |
| 235 | let bytes = 0 |
| 236 | for (let i = lines.length - 1; i >= 0 && out.length < maxLines; i--) { |
| 237 | const size = Buffer.byteLength(lines[i], "utf-8") + (out.length > 0 ? 1 : 0) |
| 238 | if (bytes + size > maxBytes) { |
| 239 | if (out.length === 0) { |
| 240 | const buf = Buffer.from(lines[i], "utf-8") |
| 241 | let start = buf.length - maxBytes |
| 242 | if (start < 0) start = 0 |
| 243 | while (start < buf.length && (buf[start] & 0xc0) === 0x80) start++ |
| 244 | out.unshift(buf.subarray(start).toString("utf-8")) |
| 245 | } |
| 246 | break |
| 247 | } |
| 248 | out.unshift(lines[i]) |
| 249 | bytes += size |
| 250 | } |
| 251 | return { |
| 252 | text: out.join("\n"), |
| 253 | cut: true, |
| 254 | } |
| 255 | } |
| 256 | |
| 257 | const parse = Effect.fn("ShellTool.parse")(function* (command: string, ps: boolean) { |
| 258 | const tree = yield* Effect.promise(() => parser().then((p) => (ps ? p.ps : p.bash).parse(command))) |
no test coverage detected