Compare commits
4 Commits
6cc2c8db3a
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
|
2dcf44bc0b
|
|||
|
d95f6a1cd6
|
|||
|
136cf16cfd
|
|||
|
2c1beda59f
|
@@ -12,7 +12,7 @@ mkdir -p "$DIST"
|
||||
cp "$SRC/index.html" "$DIST/index.html"
|
||||
|
||||
# Cache-bust assets by appending a content hash to filenames
|
||||
for ext in css js jpeg png svg; do
|
||||
for ext in css js jpeg png svg ico; do
|
||||
for file in "$SRC"/*."$ext"; do
|
||||
[ -f "$file" ] || continue
|
||||
name=$(basename "$file" | sed "s/\.$ext$//")
|
||||
@@ -29,7 +29,7 @@ for ext in css js jpeg png svg; do
|
||||
js)
|
||||
sed -i "s|src=\"${name}.${ext}\"|src=\"${newname}\"|g" "$DIST/index.html"
|
||||
;;
|
||||
jpeg|png|svg)
|
||||
jpeg|png|svg|ico)
|
||||
sed -i "s|\"${name}.${ext}\"|\"${newname}\"|g" "$DIST/index.html"
|
||||
;;
|
||||
esac
|
||||
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 2.0 MiB |
@@ -5,6 +5,7 @@
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Reese Wells - Self-Hosting & Infrastructure</title>
|
||||
<link rel="icon" type="image/png" href="favicon.ico">
|
||||
<link rel="stylesheet" href="style.css">
|
||||
</head>
|
||||
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 27 KiB After Width: | Height: | Size: 125 KiB |
+8
-1
@@ -269,6 +269,12 @@ body {
|
||||
background: #ef4444;
|
||||
}
|
||||
|
||||
.vim-block-cursor {
|
||||
background: #22c55e;
|
||||
color: #0a0a0c;
|
||||
border-radius: 1px;
|
||||
}
|
||||
|
||||
@keyframes cursorBlink {
|
||||
|
||||
0%,
|
||||
@@ -1633,7 +1639,7 @@ footer p {
|
||||
position: fixed;
|
||||
top: 80px;
|
||||
right: 20px;
|
||||
z-index: 1000;
|
||||
z-index: 10001;
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
gap: 0.75rem;
|
||||
@@ -1652,6 +1658,7 @@ footer p {
|
||||
pointer-events: auto;
|
||||
animation: toastIn 0.4s cubic-bezier(0.16, 1, 0.3, 1);
|
||||
max-width: 340px;
|
||||
z-index: 10001;
|
||||
}
|
||||
|
||||
.toast.removing {
|
||||
|
||||
+460
-4
@@ -62,6 +62,7 @@ function createTerminal(face) {
|
||||
let tabMatches = [];
|
||||
let tabBaseInput = '';
|
||||
let isTabCompleting = false;
|
||||
let inVimMode = false;
|
||||
|
||||
const allCommands = [
|
||||
'ls', 'ss', 'clear', 'exit', 'rm -rf /', 'sudo su -', 'sudo -i',
|
||||
@@ -72,7 +73,7 @@ function createTerminal(face) {
|
||||
'systemctl list-units', 'systemctl list-units --type=service --state=running --no-pager',
|
||||
'ip addr show', 'df -h', 'free -h',
|
||||
'ps aux', 'ps aux --sort=-%mem | head -10',
|
||||
'neofetch', 'sl', 'help', 'echo', 'curl', 'wget', 'apt', 'dnf'
|
||||
'neofetch', 'sl', 'help', 'echo', 'curl', 'wget', 'apt', 'dnf', 'vim'
|
||||
];
|
||||
|
||||
function updateDisplay(text) {
|
||||
@@ -119,10 +120,12 @@ function createTerminal(face) {
|
||||
'ps aux --sort=-%mem | head -10': 'USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\nreese 1242 2.1 12.4 4285632 3932160 ? Sl May15 42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker 2341 1.2 6.8 8562348 2156032 ? Sl May15 28:45 /usr/bin/dockerd -H fd://\nreese 3456 0.8 3.2 2845632 1015808 ? Sl May15 18:22 /opt/open-webui/server\nreese 4567 0.5 2.1 1562348 665600 ? Sl May15 12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot 5678 0.3 1.4 945632 448000 ? Ssl May15 8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese 6789 0.2 1.1 745632 348000 ? Ssl May15 5:45 /usr/bin/podman run --name homepage\nroot 7890 0.1 0.8 545632 256000 ? Ssl May15 3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
|
||||
'neofetch': ` 'c. reese@homelab\n ,xNMM. ----------------------\n .OMMMMo OS: Fedora Linux 69 (Workstation Edition) x86_64\n OMMM0, Host: custom-build\n .;loddo:' loolloddol;. Kernel: 6.8.0\n cKMMMMMMMMMMNWMMMMMMMMMM0: Uptime: 42 days, 3 hours\n .KMMMMMMMMMMMMMMMMMMMMMMMWd. Packages: 2847 (dnf)\n XMMMMMMMMMMMMMMMMMMMMMMMX. Shell: bash 5.2.26\n;MMMMMMMMMMMMMMMMMMMMMMMM: Resolution: 2560x1440\n:MMMMMMMMMMMMMMMMMMMMMMMM: DE: GNOME 46.1\n.MMMMMMMMMMMMMMMMMMMMMMMMX. WM: Mutter\n kMMMMMMMMMMMMMMMMMMMMMMMMWd. Terminal: /dev/pts/0\n .XMMMMMMMMMMMMMMMMMMMMMMMMMMk CPU: AMD Ryzen 9 7900X (24) @ 5.6GHz\n .XMMMMMMMMMMMMMMMMMMMMMMK. GPU: NVIDIA GeForce RTX 4090\n kMMMMMMMMMMMMMMMMMMMMd GPU: AMD Ryzen Built-in\n ;KMMMMMMMWXXWMMMMMMMk. Memory: 8.2Gi / 31Gi\n .cooc,. .,coo:.\n\n<span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span>`,
|
||||
'sl': '____\n|DD|____T_\n|_ |_____|<\n @-@-@-oo\\',
|
||||
'help': 'Available commands:\n ls List directory contents\n pwd Print working directory\n whoami Print current user\n hostname Print hostname\n date Print current date/time\n uname Print system information\n uptime Print system uptime\n id Print user identity\n cat Print file contents (try: cat /etc/os-release)\n docker List running containers\n podman List running pods\n systemctl List running systemd services\n ss Show listening ports\n ip Show network interfaces\n df Show disk usage\n free Show memory usage\n ps Show running processes\n neofetch System info display\n sl Steam locomotive\n help Show this help message',
|
||||
'vim': 'vim: Enter the terminal text editor. Type :q to quit.',
|
||||
'help': 'Available commands:\n ls List directory contents\n pwd Print working directory\n whoami Print current user\n hostname Print hostname\n date Print current date/time\n uname Print system information\n uptime Print system uptime\n id Print user identity\n cat Print file contents (try: cat /etc/os-release)\n docker List running containers\n podman List running pods\n systemctl List running systemd services\n ss Show listening ports\n ip Show network interfaces\n df Show disk usage\n free Show memory usage\n ps Show running processes\n vim Terminal text editor (try: vim or vim filename)\n neofetch System info display\n sl Steam locomotive\n help Show this help message',
|
||||
};
|
||||
|
||||
terminal.addEventListener('keydown', (e) => {
|
||||
if (inVimMode) return;
|
||||
if (e.key === 'ArrowUp') {
|
||||
e.preventDefault();
|
||||
if (historyIndex < commandHistory.length - 1) {
|
||||
@@ -208,6 +211,456 @@ function createTerminal(face) {
|
||||
content.innerHTML = '';
|
||||
}
|
||||
|
||||
if (cmdText.startsWith('vim')) {
|
||||
const filename = cmdText.split(' ').slice(1).join(' ') || '';
|
||||
let vimBuffer = ['Welcome to vim (simulated)!'];
|
||||
let vimLineNum = 0;
|
||||
let scrollOffset = 0;
|
||||
let vimStatus = '~';
|
||||
let vimCol = 0;
|
||||
let showSplash = false;
|
||||
inVimMode = true;
|
||||
|
||||
// Hide the mobile input so it doesn't intercept vim keystrokes
|
||||
mobileInput.style.display = 'none';
|
||||
|
||||
// Create a full-screen vim overlay
|
||||
const vimOverlay = document.createElement('div');
|
||||
vimOverlay.style.position = 'fixed';
|
||||
vimOverlay.style.inset = '0';
|
||||
vimOverlay.style.background = '#0a0a0c';
|
||||
vimOverlay.style.fontFamily = "'SF Mono', 'Fira Code', 'Cascadia Code', monospace";
|
||||
vimOverlay.style.fontSize = '0.85rem';
|
||||
vimOverlay.style.lineHeight = '1.5';
|
||||
vimOverlay.style.color = '#22c55e';
|
||||
vimOverlay.style.display = 'flex';
|
||||
vimOverlay.style.flexDirection = 'column';
|
||||
vimOverlay.style.zIndex = '10000';
|
||||
vimOverlay.style.padding = '12px 24px';
|
||||
vimOverlay.style.overflow = 'hidden';
|
||||
|
||||
document.body.appendChild(vimOverlay);
|
||||
|
||||
const lineNums = [];
|
||||
const lineTexts = [];
|
||||
const vimLines = [];
|
||||
const linesContainer = document.createElement('div');
|
||||
linesContainer.style.flexGrow = '1';
|
||||
linesContainer.style.minHeight = '0';
|
||||
linesContainer.style.overflowY = 'auto';
|
||||
linesContainer.style.display = 'flex';
|
||||
linesContainer.style.flexDirection = 'column';
|
||||
linesContainer.style.scrollbarWidth = 'none';
|
||||
linesContainer.style.msOverflowStyle = 'none';
|
||||
|
||||
function createLineElement() {
|
||||
const line = document.createElement('div');
|
||||
line.style.whiteSpace = 'pre';
|
||||
line.style.flexShrink = '0';
|
||||
const numSpan = document.createElement('span');
|
||||
numSpan.style.color = '#666';
|
||||
numSpan.style.marginRight = '8px';
|
||||
numSpan.style.userSelect = 'none';
|
||||
numSpan.style.display = 'inline-block';
|
||||
numSpan.style.width = '3ch';
|
||||
const textSpan = document.createElement('span');
|
||||
line.appendChild(numSpan);
|
||||
line.appendChild(textSpan);
|
||||
return line;
|
||||
}
|
||||
|
||||
function createSplashLine(text) {
|
||||
const line = document.createElement('div');
|
||||
line.style.whiteSpace = 'pre';
|
||||
line.style.flexShrink = '0';
|
||||
const textSpan = document.createElement('span');
|
||||
line.appendChild(textSpan);
|
||||
return { line, textSpan };
|
||||
}
|
||||
|
||||
if (!filename) {
|
||||
showSplash = true;
|
||||
const splashText = [
|
||||
'',
|
||||
' VIM - Vi sIgnificantly worse M',
|
||||
'',
|
||||
' version 0.0.0-alpha',
|
||||
' by disappointed programmers et al.',
|
||||
' Modified by https://www.reddit.com/r/vim/',
|
||||
' Vim is open source and you will figure it out',
|
||||
'',
|
||||
' Please send help.',
|
||||
'',
|
||||
' type :q<Enter> to escape this regret',
|
||||
' type :help<Enter> or <F1> for on-line help',
|
||||
' type :help version0<Enter> for version info',
|
||||
'',
|
||||
];
|
||||
|
||||
for (const text of splashText) {
|
||||
const { line, textSpan } = createSplashLine(text);
|
||||
linesContainer.appendChild(line);
|
||||
lineTexts.push(textSpan);
|
||||
vimLines.push(line);
|
||||
}
|
||||
|
||||
vimBuffer = splashText;
|
||||
vimLineNum = 0;
|
||||
vimCol = 0;
|
||||
} else {
|
||||
const line = createLineElement();
|
||||
linesContainer.appendChild(line);
|
||||
lineNums.push(line.children[0]);
|
||||
lineTexts.push(line.children[1]);
|
||||
vimLines.push(line);
|
||||
vimBuffer = ['Welcome to ' + filename + '!'];
|
||||
vimLineNum = 0;
|
||||
vimCol = 0;
|
||||
}
|
||||
|
||||
vimOverlay.appendChild(linesContainer);
|
||||
|
||||
// Status bar at the bottom
|
||||
const statusLine = document.createElement('div');
|
||||
statusLine.style.marginTop = 'auto';
|
||||
statusLine.style.borderTop = '1px solid #444';
|
||||
statusLine.style.paddingTop = '4px';
|
||||
statusLine.style.color = '#ccc';
|
||||
statusLine.style.flexShrink = '0';
|
||||
vimOverlay.appendChild(statusLine);
|
||||
|
||||
// File info at the very bottom
|
||||
const fileInfo = document.createElement('div');
|
||||
fileInfo.style.color = '#888';
|
||||
fileInfo.style.flexShrink = '0';
|
||||
vimOverlay.appendChild(fileInfo);
|
||||
|
||||
function escapeHtml(str) {
|
||||
const div = document.createElement('div');
|
||||
div.textContent = str;
|
||||
return div.innerHTML;
|
||||
}
|
||||
|
||||
function vimRender() {
|
||||
// Ensure we have enough line elements
|
||||
while (vimLines.length < vimBuffer.length) {
|
||||
let newLine;
|
||||
if (showSplash) {
|
||||
const { line, textSpan } = createSplashLine('');
|
||||
newLine = line;
|
||||
linesContainer.appendChild(line);
|
||||
lineTexts.push(textSpan);
|
||||
} else {
|
||||
newLine = createLineElement();
|
||||
linesContainer.appendChild(newLine);
|
||||
lineNums.push(newLine.children[0]);
|
||||
lineTexts.push(newLine.children[1]);
|
||||
}
|
||||
vimLines.push(newLine);
|
||||
}
|
||||
|
||||
// Update all visible lines
|
||||
for (let i = 0; i < vimBuffer.length; i++) {
|
||||
if (showSplash) {
|
||||
lineTexts[i].textContent = vimBuffer[i] || '';
|
||||
} else {
|
||||
lineNums[i].textContent = (i + 1);
|
||||
const lineText = vimBuffer[i] || '';
|
||||
if (i === vimLineNum && (vimStatus === '-- INSERT --' || vimStatus === '~')) {
|
||||
const col = vimCol;
|
||||
const before = lineText.slice(0, col);
|
||||
const after = lineText.slice(col);
|
||||
if (after.length > 0) {
|
||||
const cursorChar = after.charAt(0);
|
||||
lineTexts[i].innerHTML = escapeHtml(before) + '<span class="vim-block-cursor">' + escapeHtml(cursorChar) + '</span>' + escapeHtml(after.slice(1));
|
||||
} else {
|
||||
lineTexts[i].innerHTML = escapeHtml(before) + '<span class="vim-block-cursor"> </span>';
|
||||
}
|
||||
} else {
|
||||
lineTexts[i].textContent = lineText;
|
||||
}
|
||||
}
|
||||
vimLines[i].style.display = '';
|
||||
}
|
||||
|
||||
// Hide unused line elements
|
||||
for (let i = vimBuffer.length; i < vimLines.length; i++) {
|
||||
vimLines[i].style.display = 'none';
|
||||
}
|
||||
|
||||
// Auto-scroll when line is above or below the viewport
|
||||
const lineEl = vimLines[vimLineNum];
|
||||
if (lineEl && lineEl.style.display !== 'none') {
|
||||
const lineBottom = lineEl.offsetTop + lineEl.offsetHeight;
|
||||
const lineTop = lineEl.offsetTop;
|
||||
if (lineBottom > linesContainer.scrollTop + linesContainer.clientHeight) {
|
||||
linesContainer.scrollTop = lineBottom - linesContainer.clientHeight;
|
||||
} else if (lineTop < linesContainer.scrollTop + 12) {
|
||||
linesContainer.scrollTop = lineTop - 12;
|
||||
}
|
||||
}
|
||||
|
||||
if (showSplash) {
|
||||
statusLine.textContent = '';
|
||||
fileInfo.textContent = '"VIM - Vi sIgnificantly worse M"';
|
||||
} else {
|
||||
statusLine.textContent = vimStatus;
|
||||
fileInfo.textContent = '"' + filename + '"';
|
||||
}
|
||||
}
|
||||
|
||||
function vimExit(message) {
|
||||
document.removeEventListener('keydown', vimHandler);
|
||||
inVimMode = false;
|
||||
mobileInput.style.display = '';
|
||||
vimOverlay.remove();
|
||||
content.innerHTML = '';
|
||||
if (message) {
|
||||
const msgLine = document.createElement('div');
|
||||
msgLine.style.whiteSpace = 'pre-wrap';
|
||||
msgLine.style.color = '#ccc';
|
||||
msgLine.textContent = message;
|
||||
content.appendChild(msgLine);
|
||||
}
|
||||
const newLine = document.createElement('div');
|
||||
newLine.innerHTML = '<span class="terminal-prompt">$</span> ';
|
||||
content.appendChild(newLine);
|
||||
const newCursor = document.createElement('span');
|
||||
newCursor.className = 'terminal-cursor';
|
||||
newLine.appendChild(newCursor);
|
||||
content.scrollTop = content.scrollHeight;
|
||||
terminal.focus();
|
||||
}
|
||||
|
||||
const vimHandler = (e) => {
|
||||
e.preventDefault();
|
||||
|
||||
if (showSplash) {
|
||||
if (e.key === 'q' && e.shiftKey) {
|
||||
vimExit();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Escape' || e.key === 'q') {
|
||||
vimExit();
|
||||
return;
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
|
||||
if (vimStatus.startsWith(':')) {
|
||||
if (e.key === 'Enter') {
|
||||
const cmd = vimStatus.slice(1).trim();
|
||||
if (cmd === 'q' || cmd === 'q!') {
|
||||
vimExit();
|
||||
return;
|
||||
}
|
||||
if (cmd === 'wq' || cmd === 'x') {
|
||||
vimExit('File saved (simulated).');
|
||||
return;
|
||||
}
|
||||
if (cmd === 'w') {
|
||||
vimStatus = 'File written (simulated).';
|
||||
vimRender();
|
||||
setTimeout(() => { vimStatus = ':'; vimRender(); }, 1000);
|
||||
return;
|
||||
}
|
||||
if (cmd.startsWith('%s/')) {
|
||||
vimStatus = 'Pattern not found (simulated).';
|
||||
vimRender();
|
||||
setTimeout(() => { vimStatus = ':'; vimRender(); }, 1000);
|
||||
return;
|
||||
}
|
||||
if (cmd === 'help') {
|
||||
vimStatus = ':q quit :w save :wq save & quit :q! force quit dd delete line i insert o open line';
|
||||
vimRender();
|
||||
setTimeout(() => { vimStatus = ':'; vimRender(); }, 3000);
|
||||
return;
|
||||
}
|
||||
vimStatus = 'Unknown command: ' + cmd;
|
||||
vimRender();
|
||||
setTimeout(() => { vimStatus = ':'; vimRender(); }, 2000);
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Escape') {
|
||||
vimStatus = '~';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Backspace') {
|
||||
vimStatus = vimStatus.slice(0, -1);
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key.length === 1) {
|
||||
vimStatus += e.key;
|
||||
vimRender();
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
if (vimStatus === '-- INSERT --') {
|
||||
if (e.key === 'Escape') {
|
||||
vimStatus = '~';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key.length === 1 && !e.ctrlKey && !e.altKey && !e.metaKey) {
|
||||
vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, vimCol) + e.key + vimBuffer[vimLineNum].slice(vimCol);
|
||||
vimCol++;
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Enter') {
|
||||
vimBuffer.splice(vimLineNum + 1, 0, '');
|
||||
vimLineNum++;
|
||||
vimCol = 0;
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'Backspace') {
|
||||
if (vimCol > 0) {
|
||||
vimCol--;
|
||||
vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, vimCol) + vimBuffer[vimLineNum].slice(vimCol + 1);
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowUp') {
|
||||
if (vimLineNum > 0) { vimLineNum--; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowDown') {
|
||||
if (vimLineNum < vimBuffer.length - 1) { vimLineNum++; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowLeft') {
|
||||
if (vimCol > 0) { vimCol--; vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowRight') {
|
||||
const maxCol = (vimBuffer[vimLineNum] || '').length;
|
||||
if (vimCol < maxCol) { vimCol++; vimRender(); }
|
||||
return;
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
|
||||
// Normal mode (~)
|
||||
if (e.key === 'Escape') {
|
||||
vimStatus = '~';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'i') {
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'I') {
|
||||
vimCol = 0;
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'a') {
|
||||
vimCol = Math.min(vimCol + 1, (vimBuffer[vimLineNum] || '').length);
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'A') {
|
||||
vimCol = (vimBuffer[vimLineNum] || '').length;
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'o') {
|
||||
vimBuffer.splice(vimLineNum + 1, 0, '');
|
||||
vimLineNum++;
|
||||
vimCol = 0;
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'O') {
|
||||
vimBuffer.splice(vimLineNum, 0, '');
|
||||
vimLineNum++;
|
||||
vimCol = 0;
|
||||
vimStatus = '-- INSERT --';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'x') {
|
||||
if (vimBuffer[vimLineNum]) {
|
||||
vimBuffer[vimLineNum] = vimBuffer[vimLineNum].slice(0, -1);
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'd' && e.altKey) {
|
||||
if (vimLineNum < vimBuffer.length - 1) {
|
||||
vimBuffer.splice(vimLineNum, 1);
|
||||
if (vimLineNum >= vimBuffer.length) vimLineNum = vimBuffer.length - 1;
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'd' && e.shiftKey) {
|
||||
if (vimLineNum < vimBuffer.length - 1) {
|
||||
vimBuffer.splice(vimLineNum, 1);
|
||||
if (vimLineNum >= vimBuffer.length) vimLineNum = vimBuffer.length - 1;
|
||||
}
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowUp') {
|
||||
if (vimLineNum > 0) { vimLineNum--; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowDown') {
|
||||
if (vimLineNum < vimBuffer.length - 1) { vimLineNum++; vimCol = Math.min(vimCol, (vimBuffer[vimLineNum] || '').length); vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowLeft') {
|
||||
if (vimCol > 0) { vimCol--; vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'ArrowRight') {
|
||||
const maxCol = (vimBuffer[vimLineNum] || '').length;
|
||||
if (vimCol < maxCol) { vimCol++; vimRender(); }
|
||||
return;
|
||||
}
|
||||
if (e.key === 'G') {
|
||||
vimLineNum = vimBuffer.length - 1;
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === 'g') {
|
||||
vimLineNum = 0;
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
if (e.key === ':') {
|
||||
vimStatus = ':';
|
||||
vimRender();
|
||||
return;
|
||||
}
|
||||
vimRender();
|
||||
};
|
||||
|
||||
document.addEventListener('keydown', vimHandler);
|
||||
|
||||
const newAchievements = checkAchievements(cmdText, isRoot);
|
||||
if (newAchievements.length > 0) {
|
||||
revealAchievements();
|
||||
newAchievements.forEach(a => showToast(a));
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
if (cmdText === 'exit') {
|
||||
if (!isRoot) {
|
||||
const newAchievements = checkAchievements(cmdText, false);
|
||||
@@ -397,7 +850,7 @@ function createTerminal(face) {
|
||||
'ps aux --sort=-%mem | head -10': 'USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND\nreese 1242 2.1 12.4 4285632 3932160 ? Sl May15 42:18 /opt/llama.cpp/build/bin/llama-server --model /models/Qwen3-30B-A3B.Q4_K_M.gguf --port 8082\ndocker 2341 1.2 6.8 8562348 2156032 ? Sl May15 28:45 /usr/bin/dockerd -H fd://\nreese 3456 0.8 3.2 2845632 1015808 ? Sl May15 18:22 /opt/open-webui/server\nreese 4567 0.5 2.1 1562348 665600 ? Sl May15 12:34 /usr/bin/python3 /opt/borg/borgmatic\nroot 5678 0.3 1.4 945632 448000 ? Ssl May15 8:12 /usr/bin/docker-proxy -p tcp:0.0.0.0:80:80\nreese 6789 0.2 1.1 745632 348000 ? Ssl May15 5:45 /usr/bin/podman run --name homepage\nroot 7890 0.1 0.8 545632 256000 ? Ssl May15 3:22 /usr/bin/docker-proxy -p tcp:0.0.0.0:443:443',
|
||||
'neofetch': ` 'c. reese@homelab\n ,xNMM. ----------------------\n .OMMMMo OS: Fedora Linux 69 (Workstation Edition) x86_64\n OMMM0, Host: custom-build\n .;loddo:' loolloddol;. Kernel: 6.8.0\n cKMMMMMMMMMMNWMMMMMMMMMM0: Uptime: 42 days, 3 hours\n .KMMMMMMMMMMMMMMMMMMMMMMMWd. Packages: 2847 (dnf)\n XMMMMMMMMMMMMMMMMMMMMMMMX. Shell: bash 5.2.26\n;MMMMMMMMMMMMMMMMMMMMMMMM: Resolution: 2560x1440\n:MMMMMMMMMMMMMMMMMMMMMMMM: DE: GNOME 46.1\n.MMMMMMMMMMMMMMMMMMMMMMMMX. WM: Mutter\n kMMMMMMMMMMMMMMMMMMMMMMMMWd. Terminal: /dev/pts/0\n .XMMMMMMMMMMMMMMMMMMMMMMMMMMk CPU: AMD Ryzen 9 7900X (24) @ 5.6GHz\n .XMMMMMMMMMMMMMMMMMMMMMMK. GPU: NVIDIA GeForce RTX 4090\n kMMMMMMMMMMMMMMMMMMMMd GPU: AMD Ryzen Built-in\n ;KMMMMMMMWXXWMMMMMMMk. Memory: 8.2Gi / 31Gi\n .cooc,. .,coo:.\n\n<span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #22c55e">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #eab308">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #3b82f6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #8b5cf6">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span><span style="color: #ec4899">███</span>`,
|
||||
'sl': '____\n|DD|____T_\n|_ |_____|<\n @-@-@-oo\\',
|
||||
'help': 'Available commands:\n ls List directory contents\n pwd Print working directory\n whoami Print current user\n hostname Print hostname\n date Print current date/time\n uname Print system information\n uptime Print system uptime\n id Print user identity\n cat Print file contents\n docker List running containers\n podman List running pods\n systemctl List running systemd services\n ss Show listening ports\n ip Show network interfaces\n df Show disk usage\n free Show memory usage\n ps Show running processes\n apt Package manager (update, install)\n curl Fetch a webpage\n wget Fetch a webpage\n neofetch System info display\n sl Steam locomotive\n clear Clear the terminal\n exit Exit to login screen\n sudo Gain root access\n rm Remove files\n echo Print text\n help Show this help message',
|
||||
'help': 'Available commands:\n ls List directory contents\n pwd Print working directory\n whoami Print current user\n hostname Print hostname\n date Print current date/time\n uname Print system information\n uptime Print system uptime\n id Print user identity\n cat Print file contents\n docker List running containers\n podman List running pods\n systemctl List running systemd services\n ss Show listening ports\n ip Show network interfaces\n df Show disk usage\n free Show memory usage\n ps Show running processes\n apt Package manager (update, install)\n curl Fetch a webpage\n wget Fetch a webpage\n vim Terminal text editor (try: vim or vim filename)\n neofetch System info display\n sl Steam locomotive\n clear Clear the terminal\n exit Exit to login screen\n sudo Gain root access\n rm Remove files\n echo Print text\n help Show this help message',
|
||||
};
|
||||
|
||||
if (cmdText.startsWith('echo ')) {
|
||||
@@ -650,8 +1103,9 @@ function createTerminal(face) {
|
||||
document.querySelector('.rack-container')?.classList.remove('opaque');
|
||||
});
|
||||
|
||||
mobileInput.addEventListener('keydown', (e) => {
|
||||
mobileInput.addEventListener('keydown', (e) => {
|
||||
if (e.key === 'Escape') {
|
||||
if (inVimMode) return;
|
||||
mobileInput.blur();
|
||||
}
|
||||
});
|
||||
@@ -741,6 +1195,8 @@ const ACHIEVEMENTS = {
|
||||
software_installer: { name: 'Software Installer', desc: 'Install a package with apt', icon: '🔧', cmd: 'apt install', prefix: true },
|
||||
fedora_updater: { name: 'Fedora Updater', desc: 'Update packages with dnf', icon: '🎯', cmd: 'dnf update' },
|
||||
fedora_installer: { name: 'Fedora Installer', desc: 'Install a package with dnf', icon: '📀', cmd: 'dnf install', prefix: true },
|
||||
vim_splash: { name: 'Vi sIgnificantly worse M', desc: 'Open vim without a filename', icon: '📝', cmd: 'vim' },
|
||||
vim_edit: { name: 'Actually Editing', desc: 'Open vim with a filename', icon: '✏️', cmd: 'vim ', prefix: true },
|
||||
};
|
||||
|
||||
// Load unlocked achievement keys from localStorage
|
||||
|
||||
Reference in New Issue
Block a user