initial commit

This commit is contained in:
Holly McFarland 2026-08-18 16:15:02 -04:00
commit 00e6045482
2 changed files with 67 additions and 0 deletions

3
README.md Normal file
View File

@ -0,0 +1,3 @@
1. Install Tampermonkey or something in your browser
2. Open [dscrtc.user.js](https://git.hollymcfarland.com/monorail/DSCRTC/src/branch/main/dscrtc.user.js#bypass=true) and read until you're comfortable that I'm not stealing your credit card data or whatever
3. Click "Raw" near the top to bring up the install screen

64
dscrtc.user.js Normal file
View File

@ -0,0 +1,64 @@
// ==UserScript==
// @name Deep Space Communications Relay Tab Completion
// @namespace https://hollymcfarland.com
// @version 2026-08-16
// @description Tab complete known definitions
// @author You
// @match https://dscr.dixonary.co.uk/
// @grant none
// ==/UserScript==
(function() {
'use strict';
document.addEventListener("keydown", (event) => {
// Only listen to tab
if (event.key !== "Tab") return;
// Only listen when message box focused
const inputEl = document.querySelector("#message-input");
if (document.activeElement !== inputEl) return;
// Don't tab out of input box
event.preventDefault();
const input = inputEl.value;
const cursorPos = inputEl.selectionStart;
// I don't even want to _think_ about how to handle tab completion if you have a range selected
if (cursorPos !== inputEl.selectionEnd) return;
// Character behind cursor should be non-whitespace
// Character after cursor should at least not be a letter
// Hopefully this accounts for _most_ reasonable signal definitions
if (!(/\S/.test(input[cursorPos-1]) && (input.length === cursorPos || /[^A-Z]/.test(input[cursorPos])))) return;
// Everything from most recent word boundary to the cursor position should be a reasonable estimate of "current signal"
const currentSignal = /[\w-_]+?$/.exec(input.slice(0, cursorPos).toUpperCase())[0];
const signals = JSON.parse(localStorage.getItem("dict")).map((s) => (s.value));
const matches = signals.filter((s) => (s.startsWith(currentSignal)));
// Give up if current signal isn't a prefix of any signal
if (!matches.length) return;
// Longest common prefix algorithm
// After loop, i contains number of additional characters (after currentSignal.length) that are shared by all matches
matches.sort();
console.log(matches);
let i = 0;
for (; i<matches[0].length; i++) {
const idx = i + currentSignal.length;
const [first, last] = [matches[0][idx], matches[matches.length-1][idx]];
if (first === undefined || last === undefined || first !== last) break;
}
const addedCharacters = matches[0].slice(currentSignal.length, currentSignal.length+i);
// Put new computed value back into text box and reposition cursor to match
inputEl.value = input.slice(0, cursorPos) + addedCharacters + input.slice(cursorPos);
inputEl.selectionStart = cursorPos + i;
inputEl.selectionEnd = cursorPos + i;
});
})();