Skip to content

Commit

Permalink
Editorapex (#87)
Browse files Browse the repository at this point in the history
editor: bracket, line number and use on apex runner
  • Loading branch information
dufoli authored May 9, 2024
1 parent 824769c commit ed3a2ec
Show file tree
Hide file tree
Showing 4 changed files with 68 additions and 47 deletions.
19 changes: 0 additions & 19 deletions addon/apex-runner.css
Original file line number Diff line number Diff line change
@@ -1,22 +1,3 @@
.line-numbers {
text-align: right;
padding: 8px 10px;
}

.line-numbers span {
counter-increment: linenumber;
}

.line-numbers span::before {
content: counter(linenumber);
display: block;
color: #506882;
}
.editor {
display: flex;
}


.class .autocomplete-icon {
-webkit-mask-image: url('chrome-extension://__MSG_@@extension_id__/images/relate.svg');
background-color: #04844B;
Expand Down
19 changes: 3 additions & 16 deletions addon/apex-runner.js
Original file line number Diff line number Diff line change
Expand Up @@ -79,7 +79,6 @@ class Model {

this.sfLink = "https://" + sfHost;
this.spinnerCount = 0;
this.numberOfLines = 1;
this.showHelp = false;
this.userInfo = "...";
this.userId = null;
Expand Down Expand Up @@ -141,7 +140,6 @@ class Model {
setEditor(editor) {
this.editor = editor;
editor.value = this.initialScript;
this.numberOfLines = this.initialScript.split("\n").length;
this.initialScript = null;
}
toggleHelp() {
Expand Down Expand Up @@ -530,12 +528,7 @@ class Model {
let selStart = vm.editor.selectionStart;
let selEnd = vm.editor.selectionEnd;
let ctrlSpace = e.ctrlSpace;
let numberOfLines = script.split("\n").length;
this.parseAnonApex(script);
if (vm.numberOfLines != numberOfLines) {
vm.numberOfLines = numberOfLines;
vm.didUpdate();
}
//TODO place suggestion over the text area with miroring text with span
//advantage is that we can provide color highlight thanks to that.
/*
Expand Down Expand Up @@ -1145,8 +1138,7 @@ class App extends React.Component {

render() {
let {model} = this.props;
let keywordColor = new Map([["{", "violet"], ["}", "violet"], ["[", "violet"], ["]", "violet"], ["(", "violet"], ["do", "violet"],
[")", "violet"], ["public", "blue"], ["private", "blue"], ["global", "blue"], ["class", "blue"], ["static", "blue"],
let keywordColor = new Map([["do", "violet"], ["public", "blue"], ["private", "blue"], ["global", "blue"], ["class", "blue"], ["static", "blue"],
["interface", "blue"], ["extends", "blue"], ["while", "violet"], ["for", "violet"], ["try", "violet"], ["catch", "violet"],
["finally", "violet"], ["extends", "violet"], ["throw", "violet"], ["new", "violet"], ["if", "violet"], ["else", "violet"]]);
return h("div", {onClick: this.onClick},
Expand Down Expand Up @@ -1204,12 +1196,7 @@ class App extends React.Component {
),
),
),
h("div", {className: "editor"},
h("div", {className: "line-numbers"},
Array(model.numberOfLines).fill(null).map((e, i) => h("span", {key: "LineNumber" + i}))
),
h(Editor, {model, keywordColor, keywordCaseSensitive: true}),
),
h(Editor, {model, keywordColor, keywordCaseSensitive: true}),
h("div", {className: "autocomplete-box"},
h("div", {className: "autocomplete-header"},
h("span", {}, model.autocompleteResults.title),
Expand All @@ -1218,7 +1205,7 @@ class App extends React.Component {
h("button", {tabIndex: 2, onClick: this.onCopyScript, title: "Copy script url", className: "copy-id"}, "Export Script")
),
),
h("div", {className: "autocomplete-results"},
h("div", {className: "autocomplete-results", style: {top: model.suggestionTop + "px", left: model.suggestionLeft + "px"}},
model.autocompleteResults.results.map(r =>
h("div", {className: "autocomplete-result", key: r.key ? r.key : r.value}, h("a", {tabIndex: 0, title: r.title, onClick: e => { e.preventDefault(); model.autocompleteClick(r); model.didUpdate(); }, href: "#", className: r.autocompleteType + " " + r.dataType}, h("div", {className: "autocomplete-icon"}), r.title), " ")
)
Expand Down
30 changes: 29 additions & 1 deletion addon/data-export.css
Original file line number Diff line number Diff line change
Expand Up @@ -696,6 +696,12 @@ button.toggle .button-icon {
overflow: auto;
height: 200px;
}
.editor-container {
display: flex;
}
.editor-wrapper {
flex-grow: 1;
}
.editor_container {
position: relative;
text-align: 'left';
Expand All @@ -720,7 +726,6 @@ button.toggle .button-icon {
border: 1px solid #DDDBDA;
vertical-align: top;
top: 0;
left: 0;
height: 100%;
width: 100%;
resize: vertical;
Expand Down Expand Up @@ -760,4 +765,27 @@ button.toggle .button-icon {
50% {
background-color: rgb(15 23 42);
}
}
.line-numbers-wrapper {
position: relative;
width: 44px;
overflow: hidden;
}

.line-numbers {
text-align: right;
padding: 8px 10px;
position: absolute;
width: 44px;
}

.line-numbers span {
counter-increment: linenumber;
}

.line-numbers span::before {
content: counter(linenumber);
display: block;
color: #506882;
font-size: .8125rem;
}
47 changes: 36 additions & 11 deletions addon/data-load.js
Original file line number Diff line number Diff line change
Expand Up @@ -776,6 +776,8 @@ export class Editor extends React.Component {
this.editorAutocompleteEvent = this.editorAutocompleteEvent.bind(this);
this.onScroll = this.onScroll.bind(this);
this.processText = this.processText.bind(this);
this.numberOfLines = 1;
this.state = {scrolltop: 0, lineHeight: 0};
}

componentDidMount() {
Expand Down Expand Up @@ -803,6 +805,7 @@ export class Editor extends React.Component {
].forEach((property) => {
editorMirror.style[property] = textareaStyles[property];
});
this.setState({lineHeight: textareaStyles.lineHeight});
editorMirror.style.borderColor = "transparent";

//const parseValue = (v) => v.endsWith("px") ? parseInt(v.slice(0, -2), 10) : 0;
Expand All @@ -816,6 +819,7 @@ export class Editor extends React.Component {
const ro = new ResizeObserver(() => {
editorInput.getBoundingClientRect().height;
editorMirror.style.height = `${editorInput.getBoundingClientRect().height}px`;
editorMirror.style.width = `${editorInput.getBoundingClientRect().width}px`;
recalculateHeight();
});
ro.observe(editorInput);
Expand Down Expand Up @@ -847,6 +851,7 @@ export class Editor extends React.Component {
if (model.editorMirror && model.editor) {
model.editorMirror.scrollTop = model.editor.scrollTop;
}
this.setState({scrolltop: model.editor.scrollTop});
}
editorAutocompleteEvent(e) {
let {model} = this.props;
Expand Down Expand Up @@ -923,9 +928,9 @@ export class Editor extends React.Component {
if (selectionStart != selectionEnd) {
model.editor.setRangeText(closeChar, selectionEnd + 1, selectionEnd + 1, "preserve");
} else if (
(e.key !== "'" && e.key !== "\"") ||
(selectionEnd + 1 < model.editor.value.length && /[\w|\s]/.test(model.editor.value.substring(selectionEnd + 1, selectionEnd + 2))) ||
selectionEnd + 1 === model.editor.value.length) {
(e.key !== "'" && e.key !== "\"")
|| (selectionEnd + 1 < model.editor.value.length && /[\w|\s]/.test(model.editor.value.substring(selectionEnd + 1, selectionEnd + 2)))
|| selectionEnd + 1 === model.editor.value.length) {
model.editor.setRangeText(closeChar, selectionEnd + 1, selectionEnd + 1, "preserve");
}
}
Expand Down Expand Up @@ -963,20 +968,23 @@ export class Editor extends React.Component {

const rect = caretEle.getBoundingClientRect();
model.setSuggestionPosition(rect.top + rect.height, rect.left);
console.log("top: " + rect.top);
}
processText(src) {
let {keywordColor, keywordCaseSensitive, model} = this.props;
let remaining = src;
let keywordMatch;
let highlighted = [];
let numberOfLines = src ? src.split("\n").length : 1;
let selStart = model.editor ? model.editor.selectionStart : 0;
//let endIndex;
let keywords = [];
for (let keyword of keywordColor.keys()) {
keywords.push(keyword);
}
let keywordRegEx = new RegExp("\\b(" + keywords.join("|") + ")\\b|(\\/\\/|\\/\\*|')", "g" + (keywordCaseSensitive ? "" : "i"));

let keywordRegEx = new RegExp("\\b(" + keywords.join("|") + ")\\b|(\\/\\/|\\/\\*|'|{|\\[|\\(|}|\\]|\\))", "g" + (keywordCaseSensitive ? "" : "i"));
const colorBrackets = ["gold", "purple", "deepskyblue"];
let bracketIndex = 0;
//yellow for function
while ((keywordMatch = keywordRegEx.exec(remaining)) !== null) {
let color = "blue";
Expand Down Expand Up @@ -1005,6 +1013,14 @@ export class Editor extends React.Component {
} else {
sentence = remaining.substring(keywordMatch.index);
}
} else if (keywordMatch[0] == "(" || keywordMatch[0] == "[" || keywordMatch[0] == "{") {
color = colorBrackets[bracketIndex % 3];
sentence = keywordMatch[0];
bracketIndex++;
} else if (keywordMatch[0] == ")" || keywordMatch[0] == "]" || keywordMatch[0] == "}") {
bracketIndex--;
color = colorBrackets[bracketIndex % 3];
sentence = keywordMatch[0];
} else {
color = keywordColor.get(keywordMatch[1].toLocaleLowerCase());
}
Expand Down Expand Up @@ -1036,7 +1052,7 @@ export class Editor extends React.Component {
}
remaining = remaining.substring(keywordMatch.index + sentence.length);
selStart -= keywordMatch.index + sentence.length;
keywordRegEx = new RegExp("\\b(" + keywords.join("|") + ")\\b|(\\/\\/|\\/\\*|')", "g" + (keywordCaseSensitive ? "" : "i"));
keywordRegEx = new RegExp("\\b(" + keywords.join("|") + ")\\b|(\\/\\/|\\/\\*|'|{|\\[|\\(|}|\\]|\\))", "g" + (keywordCaseSensitive ? "" : "i"));
}
if (selStart > 0) {
highlighted.push({value: remaining.substring(0, selStart), attributes: {style: {color: "black"}, key: "hl" + highlighted.length}});
Expand All @@ -1046,14 +1062,23 @@ export class Editor extends React.Component {
if (remaining) {
highlighted.push({value: remaining, attributes: {style: {color: "black"}, key: "hl" + highlighted.length}});
}
return highlighted;
return {highlighted, numberOfLines};
}
render() {
let {model} = this.props;
let highlighted = this.processText(model.editor ? model.editor.value : "");
return h("div", {className: "editor_container"},
h("div", {ref: "editorMirror", className: "editor_container_mirror"}, highlighted.map(s => h("span", s.attributes, s.value))),
h("textarea", {id: "editor", autoComplete: "off", autoCorrect: "off", spellCheck: "false", autoCapitalize: "off", className: "editor_textarea", ref: "editor", onScroll: this.onScroll, onKeyUp: this.editorAutocompleteEvent, onMouseUp: this.editorAutocompleteEvent, onSelect: this.editorAutocompleteEvent, onInput: this.editorAutocompleteEvent, onKeyDown: this.handlekeyDown, style: {maxHeight: (model.winInnerHeight - 200) + "px"}})
let {highlighted, numberOfLines} = this.processText(model.editor ? model.editor.value : "");
return h("div", {className: "editor_container", style: {maxHeight: (model.winInnerHeight - 200) + "px"}},
h("div", {className: "editor-container"},
h("div", {className: "line-numbers-wrapper", style: {lineHeight: this.state.lineHeight}},
h("div", {className: "line-numbers", style: {top: -this.state.scrolltop + "px"}},
Array(numberOfLines).fill(null).map((e, i) => h("span", {key: "LineNumber" + i}))
)
),
h("div", {className: "editor-wrapper"},
h("div", {ref: "editorMirror", className: "editor_container_mirror"}, highlighted.map(s => h("span", s.attributes, s.value))),
h("textarea", {id: "editor", autoComplete: "off", autoCorrect: "off", spellCheck: "false", autoCapitalize: "off", className: "editor_textarea", ref: "editor", onScroll: this.onScroll, onKeyUp: this.editorAutocompleteEvent, onMouseUp: this.editorAutocompleteEvent, onSelect: this.editorAutocompleteEvent, onInput: this.editorAutocompleteEvent, onKeyDown: this.handlekeyDown})
)
)
);
}
}

0 comments on commit ed3a2ec

Please sign in to comment.