// ==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