NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Datacamp Select Next Underscore // @version 1.2 // @grant unsafeWindow // @include https://campus.datacamp.com/courses/* // @license MIT // @updateURL https://openuserjs.org/meta/ptrharmonic/Datacamp_Select_Next_Underscore.meta.js // @downloadURL https://openuserjs.org/install/ptrharmonic/Datacamp_Select_Next_Underscore.user.js // @copyright 2023, ptrharmonic (https://openuserjs.org/users/ptrharmonic) // ==/UserScript== // Adapted from here https://stackoverflow.com/a/39165137 function FindReact(dom, traverseUp = 0) { const key = Object.keys(dom.wrappedJSObject).find(key=>{ return key.startsWith("__reactFiber$") // react 17+ || key.startsWith("__reactInternalInstance$"); // react <17 }); const domFiber = dom.wrappedJSObject[key]; if (domFiber == null) return null; // react <16 if (domFiber._currentElement) { let compFiber = domFiber._currentElement._owner; for (let i = 0; i < traverseUp; i++) { compFiber = compFiber._currentElement._owner; } return compFiber._instance; } // react 16+ const GetCompFiber = fiber=>{ //return fiber._debugOwner; // this also works, but is __DEV__ only let parentFiber = fiber.return; while (typeof parentFiber.type == "string") { parentFiber = parentFiber.return; } return parentFiber; }; let compFiber = GetCompFiber(domFiber); for (let i = 0; i < traverseUp; i++) { compFiber = GetCompFiber(compFiber); } return compFiber.stateNode; } let editor = null; const getEditor = () => { if (editor != null) { // console.log(editor.getDomNode()); if (editor.getDomNode() != null) { return; } } let elem = document.getElementsByClassName("react-monaco-editor-container")[0]; editor = FindReact(elem).editor; // console.log(editor); let currentPos = editor.getPosition(); let text = editor.getModel().getLinesContent() console.log(currentPos, text); } const getNextUnderscore = () => { let currentPos = editor.getPosition(); let text = editor.getModel().getLinesContent(); let startLine = currentPos.lineNumber - 1; for (let i=startLine;i<text.length;i++) { if (i == startLine) { let index = text[i].indexOf("____", currentPos.column - 1); if (index != -1) { return new unsafeWindow.monaco.Position(i + 1, index + 1); } } else { let index = text[i].indexOf("____"); if (index != -1) { return new unsafeWindow.monaco.Position(i + 1, index + 1); } } } return null; } function reverseString(str) { return str.split("").reverse().join(""); } const getPrevUnderscore = () => { let currentPos = editor.getPosition(); let text = editor.getModel().getLinesContent(); let startLine = currentPos.lineNumber - 1; for (let i=startLine;i>0;i--) { // reverse the string so we can search in the opposite direction let line = reverseString(text[i]); if (i == startLine) { // If the cursor is to the left of some underlines, skip it let add = 0; let subst = text[i].substring(currentPos.column - 1 - 4, currentPos.column - 1); console.log(subst, subst === "____"); if (subst === "____") { add = 4; } let index = line.indexOf("____", line.length - currentPos.column + add); if (index != -1) { return new unsafeWindow.monaco.Position(i + 1, line.length - index + 1 - 4); } } else { let index = line.indexOf("____"); if (index != -1) { return new unsafeWindow.monaco.Position(i + 1, line.length - index + 1 - 4); } } } return null; } const next = (prev) => { getEditor(); let nextPos; if (prev) { // console.log("prev"); nextPos = getPrevUnderscore(); } else { nextPos = getNextUnderscore(); } // editor.setPosition(nextPos); editor.setSelection(new unsafeWindow.monaco.Range(nextPos.lineNumber, nextPos.column, nextPos.lineNumber, nextPos.column + 4)); } window.addEventListener("keydown", (event) => { let e = event; // e.preventDefault(); // console.log(event, event.key, e.ctrlKey); if (e.key.toLowerCase() == "u" && e.ctrlKey) { // console.log("next!") e.preventDefault(); next(e.shiftKey); } });