Skip to content

Commit 8bc1256

Browse files
committed
Emphasise important data
1 parent 0e91bc9 commit 8bc1256

File tree

2 files changed

+87
-70
lines changed

2 files changed

+87
-70
lines changed

arduino-ide-extension/src/browser/serial/decode/decode-output.tsx

Lines changed: 78 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import * as React from '@theia/core/shared/react';
22
import { Event } from '@theia/core/lib/common/event';
33
import { DisposableCollection } from '@theia/core/lib/common/disposable';
4-
// import { areEqual } from 'react-window';
4+
import { spawnCommand } from '../../../node/exec-util';
55

66
export type Line = { message: string; lineLen: number };
7+
export type Element = {
8+
address: string;
9+
function: string;
10+
path: {
11+
value: string;
12+
isLink: boolean;
13+
}
14+
lineNumber: string
15+
};
716

817
export class DecodeOutput extends React.Component<
918
DecodeOutput.Props,
@@ -13,41 +22,83 @@ export class DecodeOutput extends React.Component<
1322
* Do not touch it. It is used to be able to "follow" the serial monitor log.
1423
*/
1524
protected toDisposeBeforeUnmount = new DisposableCollection();
16-
private listRef: React.RefObject<any>;
1725

1826
constructor(props: Readonly<DecodeOutput.Props>) {
1927
super(props);
20-
this.listRef = React.createRef();
2128
this.state = {
22-
lines: [],
23-
charCount: 0,
24-
text: '',
29+
elements: [],
2530
};
2631
}
2732

28-
decodeText = (value: string) => {
29-
this.setState({ text: value });
33+
isClientPath = async (path:string): Promise<boolean> => {
34+
return await spawnCommand("cd", [
35+
path
36+
], (err) => err)
37+
.then((data) => true)
38+
.catch(err => false)
39+
}
40+
41+
openFinder = async (path:string) => {
42+
await spawnCommand("open", [
43+
path
44+
]);
45+
}
46+
47+
retrievePath = (dirPath:string) => {
48+
return dirPath.substring(0,dirPath.lastIndexOf("/")+1);
49+
}
50+
51+
decodeText = async (value: string) => {
52+
const lines = value.split("\n");
53+
54+
// Remove the extra newline at the end
55+
lines.pop();
56+
const elements : Array<Element> = [];
57+
for(let i=0;i<lines.length;i++) {
58+
let line = lines[i].split(/(?!\(.*)\s(?![^(]*?\))/g);
59+
if(line[0] === "") {
60+
line.shift();
61+
}
62+
let pathSplit = line[3].split(":");
63+
let obj: Element = {
64+
address: line[0],
65+
function: line[1],
66+
path: {
67+
value: pathSplit[0],
68+
isLink: false,
69+
},
70+
lineNumber: pathSplit[1]
71+
};
72+
if(await this.isClientPath(this.retrievePath(pathSplit[0]))) {
73+
obj = {
74+
address: line[0],
75+
function: line[1],
76+
path: {
77+
value: pathSplit[0],
78+
isLink: true,
79+
},
80+
lineNumber: pathSplit[1]
81+
};
82+
}
83+
elements.push(obj);
84+
}
85+
this.setState({ elements });
3086
};
3187

3288
override render(): React.ReactNode {
3389
return (
34-
// <List
35-
// className="serial-monitor-messages"
36-
// height={this.props.height}
37-
// itemData={
38-
// {
39-
// lines: this.state.lines,
40-
// } as any
41-
// }
42-
// itemCount={this.state.lines.length}
43-
// itemSize={18}
44-
// width={'100%'}
45-
// style={{ whiteSpace: 'nowrap' }}
46-
// ref={this.listRef}
47-
// >
48-
// {Row}
49-
// </List>
50-
<div style={{ whiteSpace: 'pre-wrap' }}>{this.state.text}</div>
90+
<div style={{ whiteSpace: 'pre-wrap' }}>
91+
{this.state.elements.map((element) => (
92+
<div style={{display: "inline-block"}}>
93+
<span style={{color: "green"}}>{element.address} </span>
94+
<span style={{color: "blue", fontWeight: "bold"}}>{element.function} </span>
95+
at
96+
{ element.path.isLink ? <a><span onClick={async () => await this.openFinder(this.retrievePath(element.path.value))}>{element.path.value}</span></a> : <span> {element.path.value} </span> }
97+
line
98+
<span style={{fontWeight: "bold"}}> {element.lineNumber}</span>
99+
</div>
100+
))}
101+
</div>
51102
);
52103
}
53104

@@ -56,10 +107,9 @@ export class DecodeOutput extends React.Component<
56107
}
57108

58109
override componentDidMount(): void {
59-
this.scrollToBottom();
60110
this.toDisposeBeforeUnmount.pushAll([
61111
this.props.clearConsoleEvent(() =>
62-
this.setState({ lines: [], charCount: 0 })
112+
this.setState({ elements: [] })
63113
),
64114
]);
65115
}
@@ -68,46 +118,16 @@ export class DecodeOutput extends React.Component<
68118
// TODO: "Your preferred browser's local storage is almost full." Discard `content` before saving layout?
69119
this.toDisposeBeforeUnmount.dispose();
70120
}
71-
72-
scrollToBottom = ((): void => {
73-
if (this.listRef.current) {
74-
this.listRef.current.scrollToItem(this.state.lines.length, 'end');
75-
}
76-
}).bind(this);
77121
}
78122

79-
// const _Row = ({
80-
// index,
81-
// style,
82-
// data,
83-
// }: {
84-
// index: number;
85-
// style: any;
86-
// data: { lines: Line[]; timestamp: boolean };
87-
// }) => {
88-
// return (
89-
// (data.lines[index].lineLen && (
90-
// <div style={style}>
91-
// <pre>
92-
// {data.lines[index].message}
93-
// </pre>
94-
// </div>
95-
// )) ||
96-
// null
97-
// );
98-
// };
99-
// const Row = React.memo(_Row, areEqual);
100-
101123
export namespace DecodeOutput {
102124
export interface Props {
103125
readonly clearConsoleEvent: Event<void>;
104126
readonly height: number;
105127
}
106128

107129
export interface State {
108-
lines: Line[];
109-
charCount: number;
110-
text: string;
130+
elements: Element[];
111131
}
112132

113133
export interface SelectOption<T> {

arduino-ide-extension/src/browser/serial/decode/decode-widget.tsx

Lines changed: 9 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ export class DecodeWidget extends ReactWidget {
127127
}
128128

129129
protected readonly onSend = (value: string) => this.doSend(value);
130+
130131
protected async doSend(value: string) {
131-
132132
const configPath = await this.configService.getConfiguration()
133133
.then(({ dataDirUri }) => (new URI(dataDirUri)).path);
134134
const boards = this.boardsServiceProvider.boardsConfig
@@ -143,31 +143,28 @@ export class DecodeWidget extends ReactWidget {
143143
}
144144
const sketchUri = (new URI(currentSketch.uri)).path;
145145
const elfPath = `${sketchUri}/build/${fqbn.split(':').join('.')}/${currentSketch.name}.ino.elf`;
146+
146147
// * enters an unkown foldername, in this case the version of gcc
147148
const xtensaPath= `${configPath}/packages/${selectedBoard}/tools/xtensa-${selectedBoard}-elf-gcc/\*/bin/xtensa-${selectedBoard}-elf-addr2line`;
148-
// Add logic here; value is the backtrace user
149-
150-
const regex = new RegExp(/[0-3]x([a-f]|[A-F]|[0-9]){8}/g);
151-
149+
const regex = new RegExp(/0x4(\d|[a-f]|[A-F]){7}/g);
152150
const arrAddresses = value.match(regex);
153-
154151
if(!arrAddresses) {
155152
return this.decodeOutputElement.current.decodeText('Provided format can not be decoded!');
156153
}
157-
158154
let decodeResult = '';
159-
160-
for(let i=0;i<arrAddresses.length; i++) {
161-
155+
for(let i=0;i<arrAddresses.length; i++) {
162156
let result = await spawnCommand(`${xtensaPath}`, [
163157
'-pfiaC',
164158
'-e',
165159
`${elfPath}`,
166160
`"${arrAddresses[i]}"`,
167161
]);
168-
decodeResult += `${result} \n`;
162+
163+
// only display rows which are readable
164+
if(!result.includes("??")) {
165+
decodeResult += `${result}`;
166+
}
169167
}
170-
171168
this.decodeOutputElement.current.decodeText(decodeResult);
172169
}
173170
}

0 commit comments

Comments
 (0)