5
5
6
6
import React from "react" ;
7
7
import { Map } from "immutable" ;
8
- import { endswith } from "@cocalc/util/misc" ;
9
- import { Ansi } from "./ansi" ;
8
+ import { Ansi , toText } from "./ansi" ;
10
9
import { TRACEBACK_STYLE } from "./style" ;
10
+ import { useFileContext } from "@cocalc/frontend/lib/file-context" ;
11
+ import { HOME_ROOT } from "@cocalc/util/consts/files" ;
11
12
12
13
interface TracebackProps {
13
14
message : Map < string , any > ;
@@ -24,23 +25,65 @@ export const Traceback: React.FC<TracebackProps> = React.memo(
24
25
const v : JSX . Element [ ] = [ ] ;
25
26
26
27
const tb = message . get ( "traceback" ) ;
28
+ const { AnchorTagComponent } = useFileContext ( ) ;
27
29
30
+ let lines : string [ ] ;
28
31
if ( typeof tb == "string" ) {
29
- v . push ( < Ansi > { tb } </ Ansi > ) ;
32
+ lines = tb . split ( "\n" ) ;
33
+ } else if ( typeof tb . forEach == "function" || Array . isArray ( tb ) ) {
34
+ // forEach detects an immutable.js object
35
+ lines = [ ] ;
36
+ for ( const x of tb ) {
37
+ lines . push ( x ) ;
38
+ }
39
+ } else {
40
+ lines = [ JSON . stringify ( tb ) ] ;
30
41
}
31
- // forEach detects an immutable object
32
- else if ( typeof tb . forEach == "function" || Array . isArray ( tb ) ) {
33
- let n : number = 0 ;
34
- for ( let x of tb ) {
35
- if ( ! endswith ( x , "\n" ) ) {
36
- x += "\n" ;
37
- }
42
+
43
+ let n : number = 0 ;
44
+ for ( let x of lines ) {
45
+ if ( ! x . endsWith ( "\n" ) ) {
46
+ x += "\n" ;
47
+ }
48
+ if ( AnchorTagComponent != null && x . startsWith ( "File " ) ) {
49
+ const { file, target, rest, line } = parseFile ( x ) ;
50
+ v . push (
51
+ < div key = { n } >
52
+ File{ " " }
53
+ < AnchorTagComponent href = { `${ target } #line=${ line } ` } >
54
+ { file } :{ line }
55
+ </ AnchorTagComponent >
56
+ < Ansi > { rest } </ Ansi >
57
+ </ div > ,
58
+ ) ;
59
+ } else {
38
60
v . push ( < Ansi key = { n } > { x } </ Ansi > ) ;
39
- n += 1 ;
40
61
}
62
+ n += 1 ;
41
63
}
42
64
43
65
return < div style = { TRACEBACK_STYLE } > { v } </ div > ;
44
66
} ,
45
- should_memoize
67
+ should_memoize ,
46
68
) ;
69
+
70
+ function parseFile ( x : string ) : {
71
+ file : string ;
72
+ rest : string ;
73
+ target : string ;
74
+ line : number ;
75
+ } {
76
+ const i = x . indexOf ( ", " ) ;
77
+ const a = toText ( x . slice ( 0 , i ) . trim ( ) ) . slice ( 5 ) . trim ( ) ;
78
+ const rest = x . slice ( i ) ;
79
+ const v = a . split ( ":" ) ;
80
+ const file = v [ 0 ] ;
81
+ let target = file ;
82
+ if ( target [ 0 ] === "/" ) {
83
+ // absolute path to the root
84
+ target = '~/' + HOME_ROOT + target ; // use root symlink
85
+ }
86
+
87
+ const line = parseInt ( v [ 1 ] ) ;
88
+ return { rest, file, target, line } ;
89
+ }
0 commit comments