WIP: vim emulation

This commit is contained in:
2024-05-15 00:51:50 +01:00
parent 8be90fe64e
commit c95923d30f
12 changed files with 263 additions and 31 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Before

Width:  |  Height:  |  Size: 483 KiB

View File

@@ -0,0 +1,117 @@
<div id="command-line" class="w-full flex flex-row bg-base">
<input
id="command-line-input"
type="text"
size="1"
class="bg-base focus:outline-none active:outline-none cursor-default caret-transparent"
/>
<div id="caret" aria-hidden="true" class="bg-text inline-block">&nbsp;</div>
<p id="status-text" class="absolute w-full h-full bg-base hidden italic">
test
</p>
</div>
<script>
const cmds: Record<string, () => void> = {
q: () => {
document.body.style.visibility = "hidden";
},
};
const container = document.getElementById("command-line") as HTMLDivElement;
const commandLineInput = document.getElementById(
"command-line-input",
) as HTMLInputElement;
const caret = document.getElementById("caret") as HTMLDivElement;
const statusText = document.getElementById(
"status-text",
) as HTMLParagraphElement;
const allowedCharRegex = /[\w\d\s!@#$%^&*()-_+=|\\~`{[}\]:;"'<,>.?/]/;
let isInCmdMode = false;
commandLineInput.value = "";
caret.style.display = "none";
function enableCmdMode() {
caret.style.display = "block";
statusText.classList.add("hidden");
commandLineInput.size = 1;
commandLineInput.value = ":";
isInCmdMode = true;
const event = new Event("cmdmodeenabled");
container.dispatchEvent(event);
}
function disableCmdMode({ clear } = { clear: true }) {
caret.style.display = "none";
isInCmdMode = false;
if (clear) {
commandLineInput.size = 1;
commandLineInput.value = "";
}
const event = new Event("cmdmodedisabled");
container.dispatchEvent(event);
}
function appendChar(event: KeyboardEvent) {
commandLineInput.value += event.key;
commandLineInput.size += 1;
}
function executeCommand() {
disableCmdMode({ clear: false });
const command = commandLineInput.value.substring(1);
const fn = cmds[command];
if (fn) {
fn();
} else {
statusText.innerHTML = `E492: Not an editor command: ${command}`;
statusText.classList.remove("hidden");
statusText.classList.add("text-red");
}
}
document.addEventListener("keydown", (event) => {
switch (event.key) {
case ":":
if (!isInCmdMode) {
enableCmdMode();
} else {
appendChar(event);
}
break;
case "Escape":
disableCmdMode();
break;
case "Backspace":
commandLineInput.value = commandLineInput.value.substring(
0,
commandLineInput.value.length - 1,
);
commandLineInput.size--;
if (commandLineInput.value === "") {
disableCmdMode();
}
break;
case "Enter":
executeCommand();
break;
default:
if (
event.key.length === 1 &&
allowedCharRegex.test(event.key) &&
isInCmdMode
) {
appendChar(event);
}
break;
}
});
</script>

View File

@@ -0,0 +1,44 @@
---
import Link from "./Link.astro";
import CommandLine from "./CommandLine.astro";
---
<div class="absolute w-full bottom-0">
<footer class="w-full bg-crust flex flex-row leading-tight">
<span
id="status-indicator"
class="bg-blue text-base inline-block leading-tight"
>&nbsp;NORMAL&nbsp;</span
>
<div class="flex flex-row bg-surface0">
<span>&nbsp;</span>
<Link href="https://github.com/kennethnym">github</Link>
<span>&nbsp;</span>
<Link href="https://x.com/kennethnym">x.com</Link>
<span>&nbsp;</span>
<Link href="mailto:kennethnym@outlook.com">email</Link>
<span>&nbsp;</span>
</div>
</footer>
<CommandLine />
</div>
<script>
const statusIndicator = document.getElementById(
"status-indicator",
) as HTMLSpanElement;
const cmdLine = document.getElementById("command-line") as HTMLDivElement;
cmdLine.addEventListener("cmdmodeenabled", () => {
statusIndicator.innerHTML = "&nbsp;COMMAND&nbsp;";
statusIndicator.classList.remove("bg-blue");
statusIndicator.classList.add("bg-peach");
console.log("cmd mode!");
});
cmdLine.addEventListener("cmdmodedisabled", () => {
statusIndicator.innerHTML = "&nbsp;NORMAL&nbsp;";
statusIndicator.classList.add("bg-blue");
statusIndicator.classList.remove("bg-peach");
});
</script>

View File

@@ -10,6 +10,7 @@ type Props = CollectionEntry<"blog">["data"];
const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
---
<!doctype html>
<html lang="en" class="latte dark:mocha">
<head>
<BaseHead title={title} description={description} image={heroImage} />
@@ -41,5 +42,5 @@ const { title, description, pubDate, updatedDate, heroImage } = Astro.props;
</main>
<hr class="py-4" />
<Footer />
</Body>
</body>
</html>

View File

@@ -1,14 +1,15 @@
---
import BaseHead from "../components/BaseHead.astro";
import Footer from "../components/Footer.astro";
import { SITE_TITLE, SITE_DESCRIPTION } from "../consts";
import Link from "../components/Link.astro";
import FormattedDate from "../components/FormattedDate.astro";
import LuaLine from "../components/LuaLine.astro";
import { getBlogs } from "../content/blog";
const posts = (await getBlogs()).sort(
(a, b) => b.data.pubDate.valueOf() - a.data.pubDate.valueOf(),
);
const currentMonth = new Date().getMonth();
---
<!doctype html>
@@ -17,34 +18,20 @@ const posts = (await getBlogs()).sort(
<BaseHead title={SITE_TITLE} description={SITE_DESCRIPTION} />
</head>
<body
class="bg-base text-text max-w-4xl m-auto p-8"
class="bg-base text-text h-screen m-auto p-8 flex items-center justify-center overflow-hidden"
>
<header>
<p class="font-bold text-2xl">kennethnym</p>
</header>
<main class="py-8">
<p>dumping ground for my thoughts. all opinions are my own.</p>
<h1 class="font-bold mt-8 mb-2 text-lg visited">current projects:</h1>
<ul class="not-prose space-y-4 md:space-y-2">
<li>
<Link href="https://polygui.org">poly</Link>: a language-agnostic,
cross-platform GUI framework for building OS-native applications.
</li>
<li>
<Link href="https://polygui.org/nanopack/introduction/">nanopack</Link
>: a zero-runtime, type-safe binary serialization format.
</li>
<li>
<Link href="https://github.com/kennethnym/StarlightLauncher"
>starlight launcher</Link
>: an open-source android launcher with a search-based ui.
</li>
</ul>
<h1 class="font-bold mt-8 mb-2 text-lg visited">my thoughts:</h1>
<ul>
<main
class="py-8 max-w-2xl flex flex-col items-center space-y-0 leading-tight"
>
<p>KENNETHNYM v23.{currentMonth + 4}</p>
<p class="leading-none">&nbsp;</p>
<p>software engineer. unpaid hhkb salesman.</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<ul class="w-full">
{
posts.map((post) => (
<li class="flex flex-row justify-between hover:bg-opacity-10 hover:bg-text -mx-2 px-2 rounded">
<li class="flex flex-row justify-between hover:bg-opacity-10 hover:bg-text -mx-2 px-2 rounded space-x-8">
<Link href={`/blog/${post.slug}`}>{post.data.title}</Link>
<FormattedDate date={post.data.pubDate} />
</li>
@@ -52,7 +39,49 @@ const posts = (await getBlogs()).sort(
}
</ul>
</main>
<hr class="py-2" />
<Footer />
<div class="absolute w-full h-full px-2 -z-10 leading-tight">
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
<p>~</p>
</div>
<LuaLine client:load />
</body>
</html>

View File

@@ -1,3 +1,43 @@
body {
font-family: monospace, monospace;
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono-400-Regular.otf") format("opentype");
font-weight: normal;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono-400-Italic.otf") format("opentype");
font-weight: normal;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono-700-Regular.otf") format("opentype");
font-weight: 700;
font-style: normal;
font-display: swap;
}
@font-face {
font-family: "CommitMono";
src: url("/fonts/CommitMono-700-Italic.otf") format("opentype");
font-weight: 700;
font-style: italic;
font-display: swap;
}
@font-face {
font-family: "NerdFont";
src: url("/fonts/SymbolsNerdFontMono-Regular.ttf") format("truetype");
font-weight: normal;
font-style: normal;
font-display: swap;
}
body {
font-family: "CommitMono", monospace, monospace;
}
.nf {
font-family: "NerdFont";
}

View File

@@ -4,6 +4,7 @@ import catppuccin from "@catppuccin/tailwindcss";
/** @type {import('tailwindcss').Config} */
export default {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
safelist: ["bg-peach", "text-red"],
theme: {
extend: {},
},