This commit is contained in:
Radon Rosborough 2020-09-14 06:06:42 -07:00
parent 779a5e6604
commit 849cf204de
6 changed files with 115 additions and 7 deletions

View File

@ -473,7 +473,7 @@ export class Session {
if (!search) {
this.send({
event: "packageSearched",
results: this.config.pkg!.popular || [],
results: [],
search: "",
});
return;

View File

@ -832,6 +832,7 @@ output = "Hello, world!"
code: `(defvar x (* 123 234))`,
},
pkg: {
index: ["https://melpa.org/#/", "https://elpa.gnu.org/"],
install: `emacs -Q --batch --eval "(progn (require 'package) (push '(\"melpa\" . \"https://melpa.org/packages/\") package-archives) (package-initialize) (unless (ignore-errors (>= (length (directory-files \"~/.emacs.d/elpa/archives\")) 4)) (package-refresh-contents)) (package-install 'NAME))"`,
uninstall: `ls ~/.emacs.d/elpa | grep -- - | grep '^NAME-[0-9]' | while read pkg; do emacs -Q --batch --eval "(progn (require 'package) (push '(\"melpa\" . \"https://melpa.org/packages/\") package-archives) (package-initialize) (unless (ignore-errors (>= (length (directory-files \"~/.emacs.d/elpa/archives\")) 4)) (package-refresh-contents)) (call-interactively 'package-delete))" <<< "$pkg"; done`,
all: `set -o pipefail; (curl -sS https://elpa.gnu.org/packages/ | grep '<td>' | grep -Eo '[^>]+</a>' | grep -Eo '^[^<]+' && curl -sS https://melpa.org/archive.json | jq -r 'keys | .[]') | sort | uniq`,
@ -1377,6 +1378,7 @@ PLEASE GIVE UP
`,
},
pkg: {
index: "https://www.npmjs.com/",
install: "yarn add NAME",
uninstall: "yarn remove NAME",
search:
@ -2114,6 +2116,7 @@ binding_irb.run(IRB.conf)
`,
},
pkg: {
index: "https://rubygems.org/",
install: "gem install --user-install NAME",
uninstall: "gem uninstall --user-install NAME",
search: `curl -sS 'https://rubygems.org/api/v1/search.json?query=NAME' | jq -r 'map(.name) | .[]'`,

View File

@ -22,6 +22,8 @@ import "bootstrap";
import "xterm/css/xterm.css";
import { autocomplete } from "./util";
const DEBUG = window.location.hash === "#debug";
const config: RijuConfig = (window as any).rijuConfig;
@ -362,6 +364,10 @@ async function main() {
if (config.pkg) {
document.getElementById("packagesButton")!.classList.add("visible");
$("#packagesModal").on("shown.bs.modal", () => {
const searchInput = document.getElementById(
"packagesSearch"
) as HTMLInputElement;
if (!packagesTermOpened) {
packagesTermOpened = true;
@ -374,19 +380,17 @@ async function main() {
packagesFitAddon.fit();
window.addEventListener("resize", () => packagesFitAddon.fit());
const searchInput = document.getElementById(
"packagesSearch"
) as HTMLInputElement;
searchInput.addEventListener(
"input",
_.debounce(() => {
sendMessage({ event: "packageSearch", search: searchInput.value });
}, 100)
);
handlePackageSearchResults = (results: string[]) => {
console.log("got results:", results);
};
handlePackageSearchResults = autocomplete(searchInput);
}
searchInput.value = "";
searchInput.focus();
});
}
}

75
frontend/src/util.ts Normal file
View File

@ -0,0 +1,75 @@
const MAX_AUTOCOMPLETE_ITEMS = 5;
export function autocomplete(
input: HTMLInputElement
): (results: string[]) => void {
let results: string[] = [];
let currentIndex = -1;
let origValue = input.value;
const close = () => {
currentIndex = -1;
for (const elt of Array.from(
input.parentElement!.getElementsByClassName("autocomplete-items")
)) {
input.parentElement!.removeChild(elt);
}
};
const updateActive = () => {
Array.from(
input.parentElement!.querySelectorAll(".autocomplete-items div")
).forEach((elt, index) => {
if (index === currentIndex) {
elt.classList.add("autocomplete-active");
} else {
elt.classList.remove("autocomplete-active");
}
});
if (currentIndex === -1) {
input.value = origValue;
} else if (currentIndex >= 0 && currentIndex < results.length) {
input.value = results[currentIndex];
}
};
// input.addEventListener("blur", () => autocompleteClose(input));
input.addEventListener("keydown", (e) => {
if (currentIndex === -1) {
origValue = input.value;
}
switch (e.key) {
case "ArrowUp":
currentIndex -= 1;
if (currentIndex < -1) {
currentIndex = results.length - 1;
}
updateActive();
e.preventDefault();
break;
case "ArrowDown":
currentIndex += 1;
if (currentIndex >= results.length) {
currentIndex = -1;
}
updateActive();
e.preventDefault();
break;
}
});
return (newResults: string[]) => {
results = newResults.slice(0, MAX_AUTOCOMPLETE_ITEMS);
if (document.activeElement !== input) return;
close();
if (results.length === 0) return;
const eltsDiv = document.createElement("div");
eltsDiv.classList.add("autocomplete-items");
results.forEach((result, index) => {
const eltDiv = document.createElement("div");
eltDiv.innerText = result;
eltDiv.addEventListener("click", () => select(index));
eltsDiv.appendChild(eltDiv);
});
input.parentNode!.appendChild(eltsDiv);
};
}

View File

@ -71,3 +71,28 @@ body {
#packagesSearch {
width: 100%;
}
.autocomplete-items {
position: absolute;
z-index: 50;
border: 1px solid #d4d4d4;
border-bottom: none;
border-radius: 4px;
overflow: hidden;
}
.autocomplete-items div {
background-color: white;
cursor: pointer;
padding: 5px 11px;
border-bottom: 1px solid #d4d4d4;
}
.autocomplete-items div:hover {
background-color: #e9e9e9;
}
.autocomplete-active {
background-color: DodgerBlue !important;
color: white;
}

View File

@ -56,5 +56,6 @@ module.exports = (_, argv) => ({
alias: {
vscode: require.resolve("monaco-languageclient/lib/vscode-compatibility"),
},
extensions: [".js", ".ts"],
},
});