[turbolizer] Display instruction ranges in turbolizer
Bug: v8:7327 Change-Id: I8cd57abf612393852532a695663175dff8e3a199 Reviewed-on: https://chromium-review.googlesource.com/1098955 Commit-Queue: Sigurd Schneider <sigurds@chromium.org> Reviewed-by: Georg Neis <neis@chromium.org> Cr-Commit-Position: refs/heads/master@{#53713}
This commit is contained in:
parent
e5e15e579e
commit
0b4552c737
@ -255,9 +255,10 @@ class CodeView extends View {
|
||||
}
|
||||
lineElement.insertBefore(lineNumberElement, lineElement.firstChild)
|
||||
// Don't add lines to source positions of not in backwardsCompatibility mode.
|
||||
if (typeof this.source['backwardsCompatibility'] === undefined) return;
|
||||
for (const sourcePosition of this.sourceResolver.linetoSourcePositions(lineNumber - 1)) {
|
||||
view.addHtmlElementToSourcePosition(sourcePosition, lineElement);
|
||||
if (this.source.backwardsCompatibility === true) {
|
||||
for (const sourcePosition of this.sourceResolver.linetoSourcePositions(lineNumber - 1)) {
|
||||
view.addHtmlElementToSourcePosition(sourcePosition, lineElement);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -22,23 +22,33 @@ class DisassemblyView extends TextView {
|
||||
return pane;
|
||||
}
|
||||
|
||||
constructor(parentId, broker) {
|
||||
constructor(parentId, broker: SelectionBroker) {
|
||||
super(parentId, broker, null);
|
||||
let view = this;
|
||||
const sourceResolver = broker.sourceResolver;
|
||||
let ADDRESS_STYLE = {
|
||||
css: 'tag',
|
||||
assignSourcePosition: function (text) {
|
||||
return SOURCE_POSITION_HEADER_STYLE.currentSourcePosition;
|
||||
},
|
||||
linkHandler: function (text, fragment) {
|
||||
if (fragment.sourcePosition === undefined) return undefined;
|
||||
return (e) => {
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.sourcePositionSelectionHandler.clear();
|
||||
const matches = text.match(/0x[0-9a-f]{8,16}\s*(?<offset>[0-9a-f]+)/);
|
||||
const offset = Number.parseInt(matches.groups["offset"], 16);
|
||||
if (!Number.isNaN(offset)) {
|
||||
const [nodes, blockId] = sourceResolver.nodesForPCOffset(offset)
|
||||
console.log("nodes for", offset, offset.toString(16), " are ", nodes);
|
||||
if (nodes.length > 0) {
|
||||
for (const nodeId of nodes) {
|
||||
view.addHtmlElementForNodeId(nodeId, fragment);
|
||||
}
|
||||
return (e) => {
|
||||
console.log(offset, nodes);
|
||||
e.stopPropagation();
|
||||
if (!e.shiftKey) {
|
||||
view.selectionHandler.clear();
|
||||
}
|
||||
view.selectionHandler.select(nodes, true);
|
||||
};
|
||||
}
|
||||
view.sourcePositionSelectionHandler.select([fragment.sourcePosition], true);
|
||||
};
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
};
|
||||
let ADDRESS_LINK_STYLE = {
|
||||
@ -82,27 +92,18 @@ class DisassemblyView extends TextView {
|
||||
}
|
||||
};
|
||||
const SOURCE_POSITION_HEADER_STYLE = {
|
||||
css: 'com',
|
||||
currentSourcePosition: undefined,
|
||||
sourcePosition: function (text) {
|
||||
let matches = view.SOURCE_POSITION_HEADER_REGEX.exec(text);
|
||||
if (!matches) return undefined;
|
||||
const scriptOffset = Number(matches[3]);
|
||||
const inliningId = matches[1] === 'not inlined' ? -1 : Number(matches[2]);
|
||||
const sp = { scriptOffset: scriptOffset, inliningId: inliningId };
|
||||
SOURCE_POSITION_HEADER_STYLE.currentSourcePosition = sp;
|
||||
return sp;
|
||||
},
|
||||
css: 'com'
|
||||
};
|
||||
view.SOURCE_POSITION_HEADER_REGEX = /^\s*--[^<]*<.*(not inlined|inlined\((\d+)\)):(\d+)>\s*--/;
|
||||
let patterns = [
|
||||
[
|
||||
[/^0x[0-9a-f]{8,16}/, ADDRESS_STYLE, 1],
|
||||
[/^0x[0-9a-f]{8,16}\s*[0-9a-f]+\ /, ADDRESS_STYLE, 1],
|
||||
[view.SOURCE_POSITION_HEADER_REGEX, SOURCE_POSITION_HEADER_STYLE, -1],
|
||||
[/^\s+-- B\d+ start.*/, BLOCK_HEADER_STYLE, -1],
|
||||
[/^.*/, UNCLASSIFIED_STYLE, -1]
|
||||
],
|
||||
[
|
||||
[/^\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
|
||||
[/^\s+[0-9a-f]+\s+[0-9a-f]+\s+/, NUMBER_STYLE, 2],
|
||||
[/^.*/, null, -1]
|
||||
],
|
||||
|
@ -6,20 +6,17 @@
|
||||
|
||||
class ScheduleView extends TextView implements PhaseView {
|
||||
schedule: Schedule;
|
||||
sourceResolver: SourceResolver;
|
||||
|
||||
createViewElement() {
|
||||
const pane = document.createElement('div');
|
||||
pane.setAttribute('id', "schedule");
|
||||
pane.innerHTML =
|
||||
`<pre id='schedule-text-pre' class='prettyprint prettyprinted'>
|
||||
<ul id='schedule-list' class='nolinenums noindent'>
|
||||
</ul>
|
||||
</pre>`;
|
||||
return pane;
|
||||
}
|
||||
|
||||
constructor(parentId, broker) {
|
||||
super(parentId, broker, null);
|
||||
this.sourceResolver = broker.sourceResolver;
|
||||
}
|
||||
|
||||
attachSelection(s) {
|
||||
@ -27,19 +24,29 @@ class ScheduleView extends TextView implements PhaseView {
|
||||
if (!(s instanceof Set)) return;
|
||||
view.selectionHandler.clear();
|
||||
view.blockSelectionHandler.clear();
|
||||
view.sourcePositionSelectionHandler.clear();
|
||||
const selected = new Array();
|
||||
for (const key of s) selected.push(key);
|
||||
view.selectionHandler.select(selected, true);
|
||||
}
|
||||
|
||||
detachSelection() {
|
||||
this.blockSelection.clear();
|
||||
return this.selection.detachSelection();
|
||||
}
|
||||
|
||||
initializeContent(data, rememberedSelection) {
|
||||
this.divNode.innerHTML = '';
|
||||
this.schedule = data.schedule
|
||||
this.addBlocks(data.schedule.blocks);
|
||||
this.attachSelection(rememberedSelection);
|
||||
}
|
||||
|
||||
createElementFromString(htmlString) {
|
||||
var div = document.createElement('div');
|
||||
div.innerHTML = htmlString.trim();
|
||||
return div.firstChild;
|
||||
}
|
||||
|
||||
|
||||
elementForBlock(block) {
|
||||
const view = this;
|
||||
function createElement(tag: string, cls: string | Array<string>, content?: string) {
|
||||
@ -63,8 +70,31 @@ class ScheduleView extends TextView implements PhaseView {
|
||||
};
|
||||
}
|
||||
|
||||
function getMarker(start, end) {
|
||||
if (start != end) {
|
||||
return ["⊙", `This node generated instructions in range [${start},${end}). ` +
|
||||
`This is currently unreliable for constants.`];
|
||||
}
|
||||
if (start != -1) {
|
||||
return ["·", `The instruction selector did not generate instructions ` +
|
||||
`for this node, but processed the node at instruction ${start}. ` +
|
||||
`This usually means that this node was folded into another node; ` +
|
||||
`the highlighted machine code is a guess.`];
|
||||
}
|
||||
return ["", `This not is not in the final schedule.`]
|
||||
}
|
||||
|
||||
function createElementForNode(node) {
|
||||
const nodeEl = createElement("div", "node");
|
||||
|
||||
const [start, end] = view.sourceResolver.getInstruction(node.id);
|
||||
const [marker, tooltip] = getMarker(start, end);
|
||||
const instrMarker = createElement("div", ["instr-marker", "com"], marker);
|
||||
instrMarker.setAttribute("title", tooltip);
|
||||
instrMarker.onclick = mkNodeLinkHandler(node.id);
|
||||
nodeEl.appendChild(instrMarker);
|
||||
|
||||
|
||||
const node_id = createElement("div", ["node-id", "tag", "clickable"], node.id);
|
||||
node_id.onclick = mkNodeLinkHandler(node.id);
|
||||
view.addHtmlElementForNodeId(node.id, node_id);
|
||||
@ -81,6 +111,7 @@ class ScheduleView extends TextView implements PhaseView {
|
||||
}
|
||||
nodeEl.appendChild(node_parameters);
|
||||
}
|
||||
|
||||
return nodeEl;
|
||||
}
|
||||
|
||||
@ -95,6 +126,13 @@ class ScheduleView extends TextView implements PhaseView {
|
||||
}
|
||||
|
||||
const schedule_block = createElement("div", "schedule-block");
|
||||
|
||||
const [start, end] = view.sourceResolver.getInstructionRangeForBlock(block.id);
|
||||
const instrMarker = createElement("div", ["instr-marker", "com"], "⊙");
|
||||
instrMarker.setAttribute("title", `Instructions range for this block is [${start}, ${end})`)
|
||||
instrMarker.onclick = mkBlockLinkHandler(block.id);
|
||||
schedule_block.appendChild(instrMarker);
|
||||
|
||||
const block_id = createElement("div", ["block-id", "com", "clickable"], block.id);
|
||||
block_id.onclick = mkBlockLinkHandler(block.id);
|
||||
schedule_block.appendChild(block_id);
|
||||
@ -128,19 +166,6 @@ class ScheduleView extends TextView implements PhaseView {
|
||||
}
|
||||
}
|
||||
|
||||
initializeContent(data, rememberedSelection) {
|
||||
this.clearText();
|
||||
this.schedule = data.schedule
|
||||
this.addBlocks(data.schedule.blocks);
|
||||
this.attachSelection(rememberedSelection);
|
||||
}
|
||||
|
||||
detachSelection() {
|
||||
this.blockSelection.clear();
|
||||
this.sourcePositionSelection.clear();
|
||||
return this.selection.detachSelection();
|
||||
}
|
||||
|
||||
lineString(node) {
|
||||
return `${node.id}: ${node.label}(${node.inputs.join(", ")})`
|
||||
}
|
||||
|
@ -84,6 +84,10 @@ class SourceResolver {
|
||||
phaseNames: Map<string, number>;
|
||||
disassemblyPhase: Phase;
|
||||
lineToSourcePositions: Map<string, Array<AnyPosition>>;
|
||||
nodeIdToInstructionRange: Array<[number, number]>;
|
||||
blockIdToInstructionRange: Array<[number, number]>;
|
||||
instructionToPCOffset: Array<number>;
|
||||
pcOffsetToInstructions: Map<number, Array<number>>;
|
||||
|
||||
|
||||
constructor() {
|
||||
@ -105,6 +109,14 @@ class SourceResolver {
|
||||
this.disassemblyPhase = undefined;
|
||||
// Maps line numbers to source positions
|
||||
this.lineToSourcePositions = new Map();
|
||||
// Maps node ids to instruction ranges.
|
||||
this.nodeIdToInstructionRange = [];
|
||||
// Maps block ids to instruction ranges.
|
||||
this.blockIdToInstructionRange = [];
|
||||
// Maps instruction numbers to PC offsets.
|
||||
this.instructionToPCOffset = [];
|
||||
// Maps PC offsets to instructions.
|
||||
this.pcOffsetToInstructions = new Map();
|
||||
}
|
||||
|
||||
setSources(sources, mainBackup) {
|
||||
@ -298,6 +310,72 @@ class SourceResolver {
|
||||
}
|
||||
}
|
||||
|
||||
readNodeIdToInstructionRange(nodeIdToInstructionRange) {
|
||||
for (const [nodeId, range] of Object.entries<[number, number]>(nodeIdToInstructionRange)) {
|
||||
this.nodeIdToInstructionRange[nodeId] = range;
|
||||
}
|
||||
}
|
||||
|
||||
readBlockIdToInstructionRange(blockIdToInstructionRange) {
|
||||
for (const [blockId, range] of Object.entries<[number, number]>(blockIdToInstructionRange)) {
|
||||
this.blockIdToInstructionRange[blockId] = range;
|
||||
}
|
||||
}
|
||||
|
||||
getInstruction(nodeId):[number, number] {
|
||||
const X = this.nodeIdToInstructionRange[nodeId];
|
||||
if (X === undefined) return [-1, -1];
|
||||
return X;
|
||||
}
|
||||
|
||||
getInstructionRangeForBlock(blockId):[number, number] {
|
||||
const X = this.blockIdToInstructionRange[blockId];
|
||||
if (X === undefined) return [-1, -1];
|
||||
return X;
|
||||
}
|
||||
|
||||
readInstructionOffsetToPCOffset(instructionToPCOffset) {
|
||||
for (const [instruction, offset] of Object.entries<number>(instructionToPCOffset)) {
|
||||
this.instructionToPCOffset[instruction] = offset;
|
||||
if (!this.pcOffsetToInstructions.has(offset)) {
|
||||
this.pcOffsetToInstructions.set(offset, []);
|
||||
}
|
||||
this.pcOffsetToInstructions.get(offset).push(instruction);
|
||||
}
|
||||
console.log(this.pcOffsetToInstructions);
|
||||
}
|
||||
|
||||
hasPCOffsets() {
|
||||
return this.pcOffsetToInstructions.size > 0;
|
||||
}
|
||||
|
||||
|
||||
nodesForPCOffset(offset): [Array<String>, Array<String>] {
|
||||
const keys = Array.from(this.pcOffsetToInstructions.keys()).sort((a, b) => b - a);
|
||||
if (keys.length === 0) return [[],[]];
|
||||
for (const key of keys) {
|
||||
if (key <= offset) {
|
||||
const instrs = this.pcOffsetToInstructions.get(key);
|
||||
const nodes = [];
|
||||
const blocks = [];
|
||||
for (const instr of instrs) {
|
||||
for (const [nodeId, range] of this.nodeIdToInstructionRange.entries()) {
|
||||
if (!range) continue;
|
||||
const [start, end] = range;
|
||||
if (start == end && instr == start) {
|
||||
nodes.push("" + nodeId);
|
||||
}
|
||||
if (start <= instr && instr < end) {
|
||||
nodes.push("" + nodeId);
|
||||
}
|
||||
}
|
||||
}
|
||||
return [nodes, blocks];
|
||||
}
|
||||
}
|
||||
return [[],[]];
|
||||
}
|
||||
|
||||
parsePhases(phases) {
|
||||
for (const [phaseId, phase] of Object.entries<Phase>(phases)) {
|
||||
if (phase.type == 'disassembly') {
|
||||
@ -305,6 +383,16 @@ class SourceResolver {
|
||||
} else if (phase.type == 'schedule') {
|
||||
this.phases.push(this.parseSchedule(phase))
|
||||
this.phaseNames.set(phase.name, this.phases.length);
|
||||
} else if (phase.type == 'instructions') {
|
||||
if (phase.nodeIdToInstructionRange) {
|
||||
this.readNodeIdToInstructionRange(phase.nodeIdToInstructionRange);
|
||||
}
|
||||
if (phase.blockIdtoInstructionRange) {
|
||||
this.readBlockIdToInstructionRange(phase.blockIdtoInstructionRange);
|
||||
}
|
||||
if (phase.instructionOffsetToPCOffset) {
|
||||
this.readInstructionOffsetToPCOffset(phase.instructionOffsetToPCOffset);
|
||||
}
|
||||
} else {
|
||||
this.phases.push(phase);
|
||||
this.recordOrigins(phase);
|
||||
|
@ -12,14 +12,11 @@ abstract class TextView extends View {
|
||||
selectionHandler: NodeSelectionHandler;
|
||||
blockSelectionHandler: BlockSelectionHandler;
|
||||
nodeSelectionHandler: NodeSelectionHandler;
|
||||
sourcePositionSelectionHandler: SelectionHandler;
|
||||
selection: MySelection;
|
||||
blockSelection: MySelection;
|
||||
sourcePositionSelection: MySelection;
|
||||
textListNode: HTMLUListElement;
|
||||
nodeIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
|
||||
blockIdToHtmlElementsMap: Map<string, Array<HTMLElement>>;
|
||||
sourcePositionToHtmlElementsMap: Map<string, Array<HTMLElement>>;
|
||||
blockIdtoNodeIds: Map<string, Array<string>>;
|
||||
nodeIdToBlockId: Array<string>;
|
||||
patterns: any;
|
||||
@ -31,12 +28,10 @@ abstract class TextView extends View {
|
||||
view.patterns = patterns;
|
||||
view.nodeIdToHtmlElementsMap = new Map();
|
||||
view.blockIdToHtmlElementsMap = new Map();
|
||||
view.sourcePositionToHtmlElementsMap = new Map();
|
||||
view.blockIdtoNodeIds = new Map();
|
||||
view.nodeIdToBlockId = [];
|
||||
view.selection = new MySelection(anyToString);
|
||||
view.blockSelection = new MySelection(anyToString);
|
||||
view.sourcePositionSelection = new MySelection(sourcePositionToStringKey);
|
||||
const selectionHandler = {
|
||||
clear: function () {
|
||||
view.selection.clear();
|
||||
@ -45,17 +40,12 @@ abstract class TextView extends View {
|
||||
},
|
||||
select: function (nodeIds, selected) {
|
||||
view.selection.select(nodeIds, selected);
|
||||
const blockIds = view.blockIdsForNodeIds(nodeIds);
|
||||
view.blockSelection.select(blockIds, selected);
|
||||
view.updateSelection();
|
||||
broker.broadcastNodeSelect(selectionHandler, view.selection.selectedKeys(), selected);
|
||||
broker.broadcastBlockSelect(view.blockSelectionHandler, blockIds, selected);
|
||||
},
|
||||
brokeredNodeSelect: function (nodeIds, selected) {
|
||||
const firstSelect = view.blockSelection.isEmpty();
|
||||
view.selection.select(nodeIds, selected);
|
||||
const blockIds = view.blockIdsForNodeIds(nodeIds);
|
||||
view.blockSelection.select(blockIds, selected);
|
||||
view.updateSelection(firstSelect);
|
||||
},
|
||||
brokeredClear: function () {
|
||||
@ -93,29 +83,6 @@ abstract class TextView extends View {
|
||||
};
|
||||
this.blockSelectionHandler = blockSelectionHandler;
|
||||
broker.addBlockHandler(blockSelectionHandler);
|
||||
const sourcePositionSelectionHandler = {
|
||||
clear: function () {
|
||||
view.sourcePositionSelection.clear();
|
||||
view.updateSelection();
|
||||
broker.broadcastClear(sourcePositionSelectionHandler);
|
||||
},
|
||||
select: function (sourcePositions, selected) {
|
||||
view.sourcePositionSelection.select(sourcePositions, selected);
|
||||
view.updateSelection();
|
||||
broker.broadcastSourcePositionSelect(sourcePositionSelectionHandler, sourcePositions, selected);
|
||||
},
|
||||
brokeredSourcePositionSelect: function (sourcePositions, selected) {
|
||||
const firstSelect = view.sourcePositionSelection.isEmpty();
|
||||
view.sourcePositionSelection.select(sourcePositions, selected);
|
||||
view.updateSelection(firstSelect);
|
||||
},
|
||||
brokeredClear: function () {
|
||||
view.sourcePositionSelection.clear();
|
||||
view.updateSelection();
|
||||
}
|
||||
};
|
||||
view.sourcePositionSelectionHandler = sourcePositionSelectionHandler;
|
||||
broker.addSourcePositionHandler(sourcePositionSelectionHandler);
|
||||
}
|
||||
|
||||
addHtmlElementForNodeId(anyNodeId: any, htmlElement: HTMLElement) {
|
||||
@ -126,14 +93,6 @@ abstract class TextView extends View {
|
||||
this.nodeIdToHtmlElementsMap.get(nodeId).push(htmlElement);
|
||||
}
|
||||
|
||||
addHtmlElementForSourcePosition(sourcePosition, htmlElement) {
|
||||
const key = sourcePositionToStringKey(sourcePosition);
|
||||
if (!this.sourcePositionToHtmlElementsMap.has(key)) {
|
||||
this.sourcePositionToHtmlElementsMap.set(key, []);
|
||||
}
|
||||
this.sourcePositionToHtmlElementsMap.get(key).push(htmlElement);
|
||||
}
|
||||
|
||||
addHtmlElementForBlockId(anyBlockId, htmlElement) {
|
||||
const blockId = anyToString(anyBlockId);
|
||||
if (!this.blockIdToHtmlElementsMap.has(blockId)) {
|
||||
@ -165,13 +124,6 @@ abstract class TextView extends View {
|
||||
if (this.divNode.parentNode == null) return;
|
||||
const mkVisible = new ViewElements(this.divNode.parentNode as HTMLElement);
|
||||
const view = this;
|
||||
for (const [nodeId, elements] of this.nodeIdToHtmlElementsMap.entries()) {
|
||||
const isSelected = view.selection.isSelected(nodeId);
|
||||
for (const element of elements) {
|
||||
mkVisible.consider(element, isSelected);
|
||||
element.classList.toggle("selected", isSelected);
|
||||
}
|
||||
}
|
||||
for (const [blockId, elements] of this.blockIdToHtmlElementsMap.entries()) {
|
||||
const isSelected = view.blockSelection.isSelected(blockId);
|
||||
for (const element of elements) {
|
||||
@ -179,11 +131,17 @@ abstract class TextView extends View {
|
||||
element.classList.toggle("selected", isSelected);
|
||||
}
|
||||
}
|
||||
for (const [sourcePositionKey, elements] of this.sourcePositionToHtmlElementsMap.entries()) {
|
||||
const isSelected = view.sourcePositionSelection.isKeySelected(sourcePositionKey);
|
||||
for (const key of this.nodeIdToHtmlElementsMap.keys()) {
|
||||
for (const element of this.nodeIdToHtmlElementsMap.get(key)) {
|
||||
element.classList.toggle("selected", false);
|
||||
}
|
||||
}
|
||||
for (const nodeId of view.selection.selectedKeys()) {
|
||||
const elements = this.nodeIdToHtmlElementsMap.get(nodeId);
|
||||
if (!elements) continue;
|
||||
for (const element of elements) {
|
||||
mkVisible.consider(element, isSelected);
|
||||
element.classList.toggle("selected", isSelected);
|
||||
mkVisible.consider(element, true);
|
||||
element.classList.toggle("selected", true);
|
||||
}
|
||||
}
|
||||
mkVisible.apply(scrollIntoView);
|
||||
@ -229,19 +187,6 @@ abstract class TextView extends View {
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof style.sourcePosition === 'function') {
|
||||
const sourcePosition = style.sourcePosition(text);
|
||||
if (sourcePosition != undefined) {
|
||||
fragment.sourcePosition = sourcePosition;
|
||||
//this.addHtmlElementForNodeId(nodeId, fragment);
|
||||
}
|
||||
}
|
||||
|
||||
if (typeof style.assignSourcePosition === 'function') {
|
||||
fragment.sourcePosition = style.assignSourcePosition();
|
||||
this.addHtmlElementForSourcePosition(fragment.sourcePosition, fragment)
|
||||
}
|
||||
|
||||
if (typeof style.assignBlockId === 'function') {
|
||||
fragment.blockId = style.assignBlockId();
|
||||
this.addNodeIdToBlockId(fragment.nodeId, fragment.blockId);
|
||||
@ -310,7 +255,7 @@ abstract class TextView extends View {
|
||||
for (let line of textLines) {
|
||||
let li = document.createElement("LI");
|
||||
li.className = "nolinenums";
|
||||
li.lineNo = lineNo++;
|
||||
li.dataset.lineNo = "" + lineNo++;
|
||||
let fragments = view.processLine(line);
|
||||
for (let fragment of fragments) {
|
||||
li.appendChild(fragment);
|
||||
|
@ -1,16 +1,16 @@
|
||||
{
|
||||
"tabSize": 2,
|
||||
"indentSize": 2,
|
||||
"convertTabsToSpaces": true,
|
||||
"insertSpaceAfterCommaDelimiter": true,
|
||||
"insertSpaceAfterSemicolonInForStatements": true,
|
||||
"insertSpaceBeforeAndAfterBinaryOperators": true,
|
||||
"insertSpaceAfterKeywordsInControlFlowStatements": true,
|
||||
"insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
|
||||
"insertSpaceBeforeFunctionParenthesis": false,
|
||||
"placeOpenBraceOnNewLineForFunctions": false,
|
||||
"placeOpenBraceOnNewLineForControlBlocks": false
|
||||
"tabSize": 2,
|
||||
"indentSize": 2,
|
||||
"convertTabsToSpaces": true,
|
||||
"insertSpaceAfterCommaDelimiter": true,
|
||||
"insertSpaceAfterSemicolonInForStatements": true,
|
||||
"insertSpaceBeforeAndAfterBinaryOperators": true,
|
||||
"insertSpaceAfterKeywordsInControlFlowStatements": true,
|
||||
"insertSpaceAfterFunctionKeywordForAnonymousFunctions": true,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingNonemptyParenthesis": false,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingNonemptyBrackets": false,
|
||||
"insertSpaceAfterOpeningAndBeforeClosingTemplateStringBraces": false,
|
||||
"insertSpaceBeforeFunctionParenthesis": false,
|
||||
"placeOpenBraceOnNewLineForFunctions": false,
|
||||
"placeOpenBraceOnNewLineForControlBlocks": false
|
||||
}
|
@ -487,17 +487,20 @@ text {
|
||||
|
||||
#schedule {
|
||||
font-family: monospace;
|
||||
margin-top: 50px;
|
||||
}
|
||||
|
||||
.schedule-block {
|
||||
margin: 5px;
|
||||
background-color: white;
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.schedule-block .block-id {
|
||||
display: inline-block;
|
||||
font-size:large;
|
||||
text-decoration: underline;
|
||||
padding-left: 1ex;
|
||||
}
|
||||
|
||||
.schedule-block .block-id:hover {
|
||||
@ -538,10 +541,6 @@ text {
|
||||
padding-right: 1ex;
|
||||
}
|
||||
|
||||
.schedule-block .nodes {
|
||||
padding-left: 5px;
|
||||
}
|
||||
|
||||
.schedule-block .nodes .node * {
|
||||
display:inline-block;
|
||||
}
|
||||
@ -568,6 +567,18 @@ text {
|
||||
content: ")";
|
||||
}
|
||||
|
||||
.schedule-block .instr-marker {
|
||||
padding-right: .5ex;
|
||||
padding-left: .5ex;
|
||||
min-width: 1ex;
|
||||
background: #EEEEEE;
|
||||
/* display: none; */
|
||||
}
|
||||
|
||||
.schedule-block > .instr-marker {
|
||||
display: inline;
|
||||
}
|
||||
|
||||
.clickable:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user