You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.js 1.9KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586
  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 = stream => {
  9. const {columns} = stream;
  10. if (!columns) {
  11. return 80;
  12. }
  13. return columns;
  14. };
  15. const fitToTerminalHeight = (stream, text) => {
  16. const terminalHeight = stream.rows || defaultTerminalHeight;
  17. const lines = text.split('\n');
  18. const toRemove = lines.length - terminalHeight;
  19. if (toRemove <= 0) {
  20. return text;
  21. }
  22. return sliceAnsi(
  23. text,
  24. stripAnsi(lines.slice(0, toRemove).join('\n')).length + 1,
  25. );
  26. };
  27. export function createLogUpdate(stream, {showCursor = false} = {}) {
  28. let previousLineCount = 0;
  29. let previousWidth = getWidth(stream);
  30. let previousOutput = '';
  31. const render = (...arguments_) => {
  32. if (!showCursor) {
  33. cliCursor.hide();
  34. }
  35. let output = arguments_.join(' ') + '\n';
  36. output = fitToTerminalHeight(stream, output);
  37. const width = getWidth(stream);
  38. if (output === previousOutput && previousWidth === width) {
  39. return;
  40. }
  41. previousOutput = output;
  42. previousWidth = width;
  43. output = wrapAnsi(output, width, {
  44. trim: false,
  45. hard: true,
  46. wordWrap: false,
  47. });
  48. stream.write(ansiEscapes.eraseLines(previousLineCount) + output);
  49. previousLineCount = output.split('\n').length;
  50. };
  51. render.clear = () => {
  52. stream.write(ansiEscapes.eraseLines(previousLineCount));
  53. previousOutput = '';
  54. previousWidth = getWidth(stream);
  55. previousLineCount = 0;
  56. };
  57. render.done = () => {
  58. previousOutput = '';
  59. previousWidth = getWidth(stream);
  60. previousLineCount = 0;
  61. if (!showCursor) {
  62. cliCursor.show();
  63. }
  64. };
  65. return render;
  66. }
  67. const logUpdate = createLogUpdate(process.stdout);
  68. export default logUpdate;
  69. export const logUpdateStderr = createLogUpdate(process.stderr);