index.js 1.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. import process from 'node:process';
  2. import ansiEscapes from 'ansi-escapes';
  3. import cliCursor from 'cli-cursor';
  4. import wrapAnsi from 'wrap-ansi';
  5. import sliceAnsi from 'slice-ansi';
  6. import stripAnsi from 'strip-ansi';
  7. const defaultTerminalHeight = 24;
  8. const getWidth = ({columns = 80}) => columns;
  9. const fitToTerminalHeight = (stream, text) => {
  10. const terminalHeight = stream.rows ?? defaultTerminalHeight;
  11. const lines = text.split('\n');
  12. const toRemove = Math.max(0, lines.length - terminalHeight);
  13. return toRemove ? sliceAnsi(text, stripAnsi(lines.slice(0, toRemove).join('\n')).length + 1) : text;
  14. };
  15. export function createLogUpdate(stream, {showCursor = false} = {}) {
  16. let previousLineCount = 0;
  17. let previousWidth = getWidth(stream);
  18. let previousOutput = '';
  19. const reset = () => {
  20. previousOutput = '';
  21. previousWidth = getWidth(stream);
  22. previousLineCount = 0;
  23. };
  24. const render = (...arguments_) => {
  25. if (!showCursor) {
  26. cliCursor.hide();
  27. }
  28. let output = fitToTerminalHeight(stream, arguments_.join(' ') + '\n');
  29. const width = getWidth(stream);
  30. if (output === previousOutput && previousWidth === width) {
  31. return;
  32. }
  33. previousOutput = output;
  34. previousWidth = width;
  35. output = wrapAnsi(output, width, {trim: false, hard: true, wordWrap: false});
  36. stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
  37. previousLineCount = output.split('\n').length;
  38. };
  39. render.clear = () => {
  40. stream.write(ansiEscapes.eraseLines(previousLineCount));
  41. reset();
  42. };
  43. render.done = () => {
  44. reset();
  45. if (!showCursor) {
  46. cliCursor.show();
  47. }
  48. };
  49. return render;
  50. }
  51. const logUpdate = createLogUpdate(process.stdout);
  52. export default logUpdate;
  53. export const logUpdateStderr = createLogUpdate(process.stderr);