Skip to content

Commit b44841b

Browse files
authored
[ZEPPELIN-6214] Fix new web app to handling carriage return
### What is this PR for? Fix an issue where the new Angular UI (zeppelin-web-angular) does not correctly handle carriage return (`\r`) characters. This causes outputs like progress bars(`#`) or status updates that use `\r` to overwrite lines to appear ugly and unnecessarily long. This implementation is a direct port of the previous logic from the classic UI (zeppelin-web), specifically based on the original implementation in [result.controller.js](https://github.com/apache/zeppelin/blob/8ca6e57f27324b1e74fc78bea5cabd176b607408/zeppelin-web/src/app/notebook/paragraph/result/result.controller.js#L527) and [result.js](https://github.com/apache/zeppelin/blob/8ca6e57f27324b1e74fc78bea5cabd176b607408/zeppelin-web/src/app/notebook/paragraph/result/result.js#L23). _Additionally, this update changes the behavior of the carriage return (`\r`) character to better emulate standard terminal functionality._ Instead of clearing the entire line, the `\r` character now moves the cursor to the beginning of the line and overwrites the existing text. This "terminal-like" partial overwrite behavior is more accurate and what most interpreters expect. This enhancement has been applied to both the classic and new UIs for consistent, standards-compliant output. ### What type of PR is it? Bug Fix ### Todos ### What is the Jira issue? [ZEPPELIN-6214] ### How should this be tested? * Any zeppelin notebook paragraph that generating progress bar (`#`) is the easiest to test this change. * Or you can reproduce the Jira Issue ticket's situation by running the code. Installing conda, set your own conda env, and set path in zeppelin is required. * For testing terminal-like CR behavior - you can run the code like below in zeppelin notebook with shell interpreter. ```bash printf 'Initializing system, please wait...\rLoading components...\n' printf 'Progress: [25%%]\rProgress: [50%%]\rProgress: [100%%]\n' ``` ### Screenshots (if appropriate) * Current Version <img width="2423" height="1021" alt="CR_Current" src="https://github.com/user-attachments/assets/e368c49d-2519-4497-ab25-f0ddfdd19a8a" /> * Fixed Version (with supporting terminal-like carriage return) <img width="2496" height="589" alt="1_CR_new" src="https://github.com/user-attachments/assets/68a88195-1058-465b-a704-4d641ab745ac" /> ### Questions: * Does the license files need to update? N * Is there breaking changes for older versions? N * Does this needs documentation? N Closes #4986 from shmruin/ZEPPELIN-6214. Signed-off-by: Philipp Dallig <philipp.dallig@gmail.com>
1 parent 890ddfe commit b44841b

File tree

2 files changed

+41
-12
lines changed

2 files changed

+41
-12
lines changed

zeppelin-web-angular/src/app/pages/workspace/share/result/result.component.ts

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -251,9 +251,34 @@ export class NotebookParagraphResultComponent implements OnInit, AfterViewInit,
251251
});
252252
}
253253

254+
private checkAndReplaceCarriageReturn(data: string): string {
255+
const str = data.replace(/\r\n/g, '\n');
256+
if (/\r/.test(str)) {
257+
const generatedLines = str.split('\n').map(line => {
258+
if (!/\r/.test(line)) {
259+
return line;
260+
}
261+
const parts = line.split('\r');
262+
let currentLine = parts[0];
263+
for (let i = 1; i < parts.length; i++) {
264+
const part = parts[i];
265+
const partLength = part.length;
266+
// apply terminal-like output. carriage return has the effect of moving output cursor to the front.
267+
const overwritten = part + currentLine.substring(partLength);
268+
currentLine = overwritten;
269+
}
270+
return currentLine;
271+
});
272+
return generatedLines.join('\n');
273+
} else {
274+
return str;
275+
}
276+
}
277+
254278
renderText(): void {
255279
const ansiUp = new AnsiUp();
256-
this.plainText = this.sanitizer.bypassSecurityTrustHtml(ansiUp.ansi_to_html(this.result.data));
280+
const processedData = this.checkAndReplaceCarriageReturn(this.result.data);
281+
this.plainText = this.sanitizer.bypassSecurityTrustHtml(ansiUp.ansi_to_html(processedData));
257282
}
258283

259284
renderImg(): void {

zeppelin-web/src/app/notebook/paragraph/result/result.js

Lines changed: 15 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -23,18 +23,22 @@ export default class Result {
2323
checkAndReplaceCarriageReturn() {
2424
const str = this.data.replace(/\r\n/g, '\n');
2525
if (/\r/.test(str)) {
26-
let newGenerated = '';
27-
let strArr = str.split('\n');
28-
for (let str of strArr) {
29-
if (/\r/.test(str)) {
30-
let splitCR = str.split('\r');
31-
newGenerated += splitCR[splitCR.length - 1] + '\n';
32-
} else {
33-
newGenerated += str + '\n';
26+
const generatedLines = str.split('\n').map((line) => {
27+
if (!/\r/.test(line)) {
28+
return line;
3429
}
35-
}
36-
// remove last "\n" character
37-
return newGenerated.slice(0, -1);
30+
const parts = line.split('\r');
31+
let currentLine = parts[0];
32+
for (let i = 1; i < parts.length; i++) {
33+
const part = parts[i];
34+
const partLength = part.length;
35+
// apply terminal-like output. carriage return has the effect of moving output cursor to the front.
36+
const overwritten = part + currentLine.substring(partLength);
37+
currentLine = overwritten;
38+
}
39+
return currentLine;
40+
});
41+
return generatedLines.join('\n');
3842
} else {
3943
return str;
4044
}

0 commit comments

Comments
 (0)