commit c20338c299359ae788f1caaa845dc37f80f1ecec Author: Darwin Cereska Date: Thu Feb 5 07:23:40 2026 -0500 Add script.js diff --git a/script.js b/script.js new file mode 100644 index 0000000..cd3c1dc --- /dev/null +++ b/script.js @@ -0,0 +1,86 @@ +// ==UserScript== +// @name Better CodeHS (Ace Optimized) +// @namespace http://tampermonkey.net/ +// @version 1.2 +// @description Enable autocomplete, Vim mode, and Gruvbox for CodeHS Ace Editor. +// @author Qyoh & Gemini +// @match https://codehs.com/* +// @grant none +// ==/UserScript== + +(function() { + 'use strict'; + + // --- UTILITIES --- + function clickButton(selector) { + const btn = document.querySelector(selector); + if (btn) btn.click(); + } + + // --- KEYBINDINGS --- + document.addEventListener('keydown', (e) => { + // Ctrl + Enter: Submit + if (e.ctrlKey && e.key === 'Enter') { + e.preventDefault(); + clickButton('.StyledButtonKind-sc-1vhfpnt-0.fSozsy.sc-bkbkJK.eraKfR'); + } + // Alt + C: Check Code + if (e.altKey && e.key === 'c') { + e.preventDefault(); + const testTab = document.querySelector('.r.c') || document.querySelector('[data-test="test-cases-tab"]'); + if (testTab) testTab.click(); + setTimeout(() => clickButton('#grading-unit-test-run.btn.btn-main.spinner'), 100); + } + }); + + // --- ACE EDITOR INJECTION --- + function injectAceFeatures() { + // CodeHS often uses 'ace' globally. If not, we try to find the editor instance. + const editorEl = document.getElementById("codehs-editor") || document.querySelector('.ace_editor'); + + if (!editorEl || !window.ace) { + setTimeout(injectAceFeatures, 1000); + return; + } + + try { + // Get the existing instance instead of creating a new one to avoid conflicts + const editor = ace.edit(editorEl); + + // Set Base Path for external modules (Vim/Themes) + ace.config.set("basePath", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/"); + ace.config.set("modePath", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/"); + ace.config.set("themePath", "https://cdnjs.cloudflare.com/ajax/libs/ace/1.32.7/"); + + // Enable Autocomplete + ace.config.loadModule("ace/ext/language_tools", function() { + editor.setOptions({ + enableBasicAutocompletion: true, + enableLiveAutocompletion: true, + enableSnippets: true + }); + }); + + // Set Theme & Vim + editor.setTheme("ace/theme/gruvbox"); + editor.setKeyboardHandler("ace/keyboard/vim"); + + console.log("Better CodeHS: Ace Editor configured successfully."); + } catch (err) { + console.error("Better CodeHS: Error initializing editor", err); + } + } + + // Initialize + window.addEventListener('load', injectAceFeatures); + // Re-run if the user navigates between assignments (SPA behavior) + let lastUrl = location.href; + new MutationObserver(() => { + const url = location.href; + if (url !== lastUrl) { + lastUrl = url; + setTimeout(injectAceFeatures, 2000); + } + }).observe(document, {subtree: true, childList: true}); + +})(); \ No newline at end of file