mirror of
https://github.com/MeexReay/poshlostios.git
synced 2025-06-23 18:12:58 +03:00
init commit
This commit is contained in:
parent
3a2e36e487
commit
8bd84c5af5
35
app/hello/hello.js
Normal file
35
app/hello/hello.js
Normal file
@ -0,0 +1,35 @@
|
||||
/*
|
||||
|
||||
Hello message
|
||||
|
||||
*/
|
||||
|
||||
const message = `Приветствуем в PoshlostiOS!!!!
|
||||
|
||||
Стандартные komandi:
|
||||
* cd <dir> - перемещение по папкам
|
||||
* hello - эт кодмана
|
||||
* ls [dir] - посмотреть список файлов
|
||||
* meow <text> - чтото пробормотать
|
||||
* posh [command] - типа херня которая команды обрабатывает
|
||||
* vget <url> <file> - скачать файлы из интернетов
|
||||
* clear - стереть терминал
|
||||
* rm <file> - удалить файл
|
||||
* mv <src> <dest> - переместить файл
|
||||
* bump <file> - создать файл
|
||||
* cp <src> <dest> - скопировать файл
|
||||
* mkdir <dir> - создать папку
|
||||
* reset - УНИЧТОЖИТЬ СИСТЕМУ, и установить заново :3
|
||||
* cat <file> - показать содержимое файла
|
||||
* ppm <i/s/r/u/A/a/l> [package] - пакетный менеджер
|
||||
|
||||
Планируется:
|
||||
* сделать hex цвета
|
||||
* прога Worldwide Objective Manuals (WOMan) которая пишет туторы по пакетам, написанию прог и описание стандартных прог
|
||||
* прога чтото наподобе nano или vi
|
||||
`
|
||||
|
||||
async function main(args) {
|
||||
writeStdout(message)
|
||||
return 0
|
||||
}
|
8
app/hello/package.json
Normal file
8
app/hello/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "hello",
|
||||
"version": "0.1.2",
|
||||
"description": "Hello Message",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "hello.js" ],
|
||||
"configs": []
|
||||
}
|
82
app/neofetch/neofetch.js
Normal file
82
app/neofetch/neofetch.js
Normal file
@ -0,0 +1,82 @@
|
||||
/*
|
||||
|
||||
neofetch - neofetch
|
||||
|
||||
*/
|
||||
|
||||
function getDurationString(start_time) {
|
||||
const now = new Date();
|
||||
const diffMs = now - start_time;
|
||||
|
||||
const seconds = Math.floor(diffMs / 1000);
|
||||
const minutes = Math.floor(seconds / 60);
|
||||
const hours = Math.floor(minutes / 60);
|
||||
const days = Math.floor(hours / 24);
|
||||
|
||||
const remainingHours = hours % 24;
|
||||
const remainingMinutes = minutes % 60;
|
||||
|
||||
let result = [];
|
||||
|
||||
if (days > 0) result.push(`${days}d`);
|
||||
if (remainingHours > 0) result.push(`${remainingHours}h`);
|
||||
result.push(`${remainingMinutes}m`);
|
||||
|
||||
return result.join(" ");
|
||||
}
|
||||
|
||||
// Function to get CPU, GPU, and memory information
|
||||
function getSystemInfo() {
|
||||
const cpuInfo = navigator.hardwareConcurrency;
|
||||
|
||||
const memoryInfo = navigator.deviceMemory;
|
||||
const totalJSHeap = performance.memory.totalJSHeapSize / (1024 * 1024);
|
||||
|
||||
const canvas = document.createElement('canvas');
|
||||
const gl = canvas.getContext('webgl') || canvas.getContext('experimental-webgl');
|
||||
let gpuInfo = null;
|
||||
|
||||
if (gl) {
|
||||
const debugInfo = gl.getExtension('WEBGL_debug_renderer_info');
|
||||
if (debugInfo) {
|
||||
gpuInfo = {
|
||||
vendor: gl.getParameter(debugInfo.UNMASKED_VENDOR_WEBGL),
|
||||
renderer: gl.getParameter(debugInfo.UNMASKED_RENDERER_WEBGL)
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
return [
|
||||
cpuInfo + " cores",
|
||||
memoryInfo ? memoryInfo * 1024 + ' MB' : 'Not supported',
|
||||
totalJSHeap.toFixed(2) + ' MB',
|
||||
gpuInfo ? `${gpuInfo.renderer}` : 'GPU Info not available'
|
||||
]
|
||||
}
|
||||
|
||||
async function main(args) {
|
||||
let [cpu, max_mem, now_mem, gpu] = getSystemInfo()
|
||||
|
||||
writeStdout(`
|
||||
█████ user@poshlosti
|
||||
███░░░█ █ ------------------
|
||||
█░░█░░░██ OS: PoshlostiOS
|
||||
█░█░░████ Uptime: ${getDurationString(start_date)}
|
||||
█░███░░░░█ Packages: ${(await listPackages()).length} (ppm)
|
||||
██░░░░░░░█ Shell: posh ${(await getInstalledPackage("posh")).version}
|
||||
█ █░░░░░░░██ Resolution: ${window.innerWidth}x${window.innerHeight}
|
||||
█░░░░░░░░█ Memory: ${now_mem} / ${max_mem}
|
||||
█░░░░░░░░█ CPU: ${cpu}
|
||||
█░░░░░░░░░█ GPU: ${gpu}
|
||||
██░░░░░░░░███████
|
||||
█░░████████▓▓▓█
|
||||
█████████▓▓▓▓▓▓▓▓▓██
|
||||
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓█
|
||||
█▓▓▓▓▓▓▓▓▓▓▓▓▓▓▓██
|
||||
██▓▓▓▓▓▓▓▓▓▓▓▓▓█
|
||||
█▓▓▓▓▓▓▓▓▓█████
|
||||
██████████
|
||||
`)
|
||||
|
||||
return 0
|
||||
}
|
8
app/neofetch/package.json
Normal file
8
app/neofetch/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "neofetch",
|
||||
"version": "0.1.1",
|
||||
"description": "neofetch damn",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "neofetch.js" ],
|
||||
"configs": []
|
||||
}
|
9
app/posh/cd.js
Normal file
9
app/posh/cd.js
Normal file
@ -0,0 +1,9 @@
|
||||
async function main(args) {
|
||||
if (!hasFile(args[1])) {
|
||||
writeStdout(`нет такой папки бро\n`)
|
||||
return 1
|
||||
}
|
||||
cwd = simplifyPath(args[1])
|
||||
writeStdout(`бро переместил тебя в ${args[1]} без б ваще обращайся\n`)
|
||||
return 0
|
||||
}
|
4
app/posh/clear.js
Normal file
4
app/posh/clear.js
Normal file
@ -0,0 +1,4 @@
|
||||
async function main(args) {
|
||||
clearTerminal()
|
||||
return 0
|
||||
}
|
4
app/posh/meow.js
Normal file
4
app/posh/meow.js
Normal file
@ -0,0 +1,4 @@
|
||||
async function main(args) {
|
||||
writeStdout(args.slice(1).join(" ")+"\n")
|
||||
return 0
|
||||
}
|
8
app/posh/package.json
Normal file
8
app/posh/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "posh",
|
||||
"version": "0.1.1",
|
||||
"description": "Poshlosti Shell",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "posh.js", "meow.js", "cd.js", "clear.js" ],
|
||||
"configs": [ "posh.json" ]
|
||||
}
|
93
app/posh/posh.js
Normal file
93
app/posh/posh.js
Normal file
@ -0,0 +1,93 @@
|
||||
/*
|
||||
|
||||
PoSh - Poshlosti Shell
|
||||
|
||||
*/
|
||||
|
||||
async function processCommand(command, args) {
|
||||
let executable = command
|
||||
if (!executable.startsWith("/")) {
|
||||
if (executable.includes("/")) {
|
||||
executable = cwd + "/" + executable
|
||||
} else {
|
||||
executable = "/app/" + executable
|
||||
}
|
||||
}
|
||||
if (!hasFile(executable) && hasFile(executable+".js")) {
|
||||
executable = executable + ".js"
|
||||
}
|
||||
executable = simplifyPath(executable)
|
||||
|
||||
if (hasFile(executable)) {
|
||||
try {
|
||||
let code = await executeCommand([executable].concat(args)).promise
|
||||
if (code != 0) {
|
||||
await writeStdout("\nСтатус код: "+code+"\n")
|
||||
}
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
await writeStdout("Не запустилася\n")
|
||||
}
|
||||
} else {
|
||||
await writeStdout("Твоя команда "+executable+" не найдена :3\n")
|
||||
}
|
||||
}
|
||||
|
||||
async function main(args) {
|
||||
if (args.length > 1) {
|
||||
await processCommand(args[1], args.slice(2))
|
||||
}
|
||||
|
||||
let history = [""]
|
||||
let history_index = 0
|
||||
|
||||
let config = JSON.parse(readFile("/config/posh.json"))
|
||||
let prompt = config["prompt"]
|
||||
let startup = config["startup"]
|
||||
|
||||
for (let command of startup) {
|
||||
let args = command.split(" ")
|
||||
await processCommand(args[0], args.slice(1))
|
||||
}
|
||||
|
||||
while (true) {
|
||||
await writeStdout(prompt.replace("{cwd}", cwd))
|
||||
|
||||
let command = await readLine((key, ctrl, alt, shift, content, pos) => {
|
||||
console.log(history, content, pos, key)
|
||||
|
||||
if (key == "ArrowDown") {
|
||||
history_index = Math.max(0, history_index - 1)
|
||||
return [history[history_index], history[history_index].length]
|
||||
}
|
||||
|
||||
if (key == "ArrowUp") {
|
||||
history_index = Math.min(history.length-1, history_index + 1)
|
||||
return [history[history_index], history[history_index].length]
|
||||
}
|
||||
|
||||
return [content, pos]
|
||||
})
|
||||
|
||||
if (command.length > 0) {
|
||||
history.splice(1, 0, command);
|
||||
history_index = 0
|
||||
|
||||
let args = command.split(" ")
|
||||
command = args[0]
|
||||
args = args.slice(1)
|
||||
|
||||
if (command == "exit") {
|
||||
if (args.length == 0) {
|
||||
return 0
|
||||
} else {
|
||||
return parseInt(args[0])
|
||||
}
|
||||
} else {
|
||||
await processCommand(command, args)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
7
app/posh/posh.json
Normal file
7
app/posh/posh.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"prompt": "[posh {cwd}]$ ",
|
||||
"startup": [
|
||||
"hello",
|
||||
"meow"
|
||||
]
|
||||
}
|
8
app/ppm/package.json
Normal file
8
app/ppm/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "ppm",
|
||||
"version": "0.1.3",
|
||||
"description": "Poshliy Package Manager",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "ppm.js" ],
|
||||
"configs": [ "ppm.json" ]
|
||||
}
|
124
app/ppm/ppm.js
Normal file
124
app/ppm/ppm.js
Normal file
@ -0,0 +1,124 @@
|
||||
/*
|
||||
|
||||
PPM - Poshliy Package Manager
|
||||
|
||||
*/
|
||||
|
||||
async function main(args) {
|
||||
if (args.length == 3 && "iurs".includes(args[1])) {
|
||||
let package = args[2]
|
||||
|
||||
if (args[1] == "i") {
|
||||
let config = JSON.parse(readFile("/config/ppm.json"))
|
||||
|
||||
for (const repo of config["repositories"]) {
|
||||
// await writeStdout(`Фетчим ${package} на репозитории ${repo}\n`)
|
||||
|
||||
let status = await installPackage(repo+"/"+package)
|
||||
|
||||
if (status == 0) {
|
||||
let pkg = await getInstalledPackage(package)
|
||||
await writeStdout(`Пакет ${pkg['name']}-${pkg['version']} установлен\n`)
|
||||
return 0
|
||||
} else if (status == 1) {
|
||||
await writeStdout("Пакет не установлен тк он уже установлен чувааак\n")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
} else if (args[1] == "u") {
|
||||
let config = JSON.parse(readFile("/config/ppm.json"))
|
||||
|
||||
for (const repo of config["repositories"]) {
|
||||
let status = await updatePackage(package, repo+"/"+package)
|
||||
|
||||
if (status == 0) {
|
||||
let pkg = await getInstalledPackage(package)
|
||||
await writeStdout(`Пакет ${pkg['name']}-${pkg['version']} обновлен\n`)
|
||||
return 0
|
||||
} else if (status == 1) {
|
||||
await writeStdout("Пакет не найден ты его установи сначала чел\n")
|
||||
return 1
|
||||
}
|
||||
}
|
||||
|
||||
await writeStdout("обнова не прошла успешна\n")
|
||||
return 1
|
||||
} else if (args[1] == "r") {
|
||||
if (await removePackage(package)) {
|
||||
await writeStdout(`Пакет ${package} удален\n`)
|
||||
} else {
|
||||
await writeStdout("Биспокойся произошла ошибко\n")
|
||||
return 1
|
||||
}
|
||||
} else if (args[1] == "s") {
|
||||
let pkg = await getInstalledPackage(package)
|
||||
for (const [key, value] of Object.entries(pkg)) {
|
||||
await writeStdout(key.charAt(0).toUpperCase()+key.slice(1)+": "+value+"\n")
|
||||
}
|
||||
}
|
||||
} else if (args.length == 2 && args[1] == "l") {
|
||||
await writeStdout("ваши покеты:\n")
|
||||
for (const package of (await listPackages())) {
|
||||
await writeStdout("- "+package["name"]+"-"+package["version"]+"\n")
|
||||
}
|
||||
} else if (args.length == 2 && args[1] == "a") {
|
||||
let config = JSON.parse(readFile("/config/ppm.json"))
|
||||
|
||||
for (const package of (await listPackages())) {
|
||||
for (const repo of config["repositories"]) {
|
||||
// await writeStdout(`Фетчим ${package["name"]} на репозитории ${repo}\n`)
|
||||
|
||||
let fetched = await fetchPackage(repo+"/"+package["name"])
|
||||
if (fetched != null) {
|
||||
if (fetched["version"] == package["version"]) {
|
||||
await writeStdout(`Пакет ${package['name']}-${package['version']} уже на последней версии\n`)
|
||||
break
|
||||
}
|
||||
|
||||
let status = await updatePackage(package["name"], repo+"/"+package["name"])
|
||||
|
||||
if (status == 0) {
|
||||
let pkg = await getInstalledPackage(package["name"])
|
||||
await writeStdout(`Пакет ${pkg['name']}-${pkg['version']} обновлен\n`)
|
||||
break
|
||||
} else if (status == 1) {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await writeStdout("Обнова прошла успешна\n")
|
||||
return 0
|
||||
} else if (args.length == 2 && args[1] == "A") {
|
||||
let config = JSON.parse(readFile("/config/ppm.json"))
|
||||
|
||||
for (const package of (await listPackages())) {
|
||||
for (const repo of config["repositories"]) {
|
||||
let status = await updatePackage(package["name"], repo+"/"+package["name"])
|
||||
|
||||
if (status == 0) {
|
||||
let pkg = await getInstalledPackage(package["name"])
|
||||
await writeStdout(`Пакет ${pkg['name']}-${pkg['version']} обновлен\n`)
|
||||
break
|
||||
} else{
|
||||
console.log(status, repo, package)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
await writeStdout("Обнова прошла успешна\n")
|
||||
return 0
|
||||
} else {
|
||||
await writeStdout("Использование:\n")
|
||||
await writeStdout(" ppm i <пакет> - установить пакет\n")
|
||||
await writeStdout(" ppm u <пакет> - обновить пакет\n")
|
||||
await writeStdout(" ppm r <пакет> - удалить пакет\n")
|
||||
await writeStdout(" ppm s <пакет> - показать инфу о пакете\n")
|
||||
await writeStdout(" ppm l - показать инфу о пакете\n")
|
||||
await writeStdout(" ppm a - обновить все пакеты\n")
|
||||
await writeStdout(" ppm A - обновить все пакеты принудительно\n")
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
5
app/ppm/ppm.json
Normal file
5
app/ppm/ppm.json
Normal file
@ -0,0 +1,5 @@
|
||||
{
|
||||
"repositories": [
|
||||
"https://poshlostios.meex.lol/app"
|
||||
]
|
||||
}
|
5
app/putils/bump.js
Normal file
5
app/putils/bump.js
Normal file
@ -0,0 +1,5 @@
|
||||
async function main(args) {
|
||||
writeFile(args[1], "")
|
||||
writeStdout(`все твой файл создан ${args[1]} такой же ты хотел жа\n`)
|
||||
return 0
|
||||
}
|
8
app/putils/cat.js
Normal file
8
app/putils/cat.js
Normal file
@ -0,0 +1,8 @@
|
||||
async function main(args) {
|
||||
if (!hasFile(args[1])) {
|
||||
writeStdout(`нет такой faila бро\n`)
|
||||
return 1
|
||||
}
|
||||
writeStdout(readFile(args[1])+"\n")
|
||||
return 0
|
||||
}
|
55
app/putils/cp.js
Normal file
55
app/putils/cp.js
Normal file
@ -0,0 +1,55 @@
|
||||
async function main(args=["","",""]) {
|
||||
let source = simplifyPath(args[1])
|
||||
let target = simplifyPath(args[2])
|
||||
|
||||
if (!hasFile(args[1])) {
|
||||
writeStdout(`нет такой херни чо мне ты даешь долбан X нету :x: :regional_symbol_x: :cross:\n`)
|
||||
return 1
|
||||
}
|
||||
|
||||
if (isFolder(source)) {
|
||||
if (!hasFile(target) || isFolder(target)) {
|
||||
let create_dirs = hasFile(target) ? [] : [target]
|
||||
let write_files = []
|
||||
|
||||
let recursive = (folder) => {
|
||||
for (const file of listFiles(folder)) {
|
||||
let path = folder+"/"+file
|
||||
if (isFolder(path)) {
|
||||
create_dirs.push(path)
|
||||
recursive(path)
|
||||
} else {
|
||||
write_files.push(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recursive(source)
|
||||
|
||||
for (const dir of create_dirs) {
|
||||
createFolder(target + dir.slice(source.length))
|
||||
}
|
||||
|
||||
for (const file of write_files) {
|
||||
let path = target + file.slice(source.length)
|
||||
writeFile(path, readFile(file))
|
||||
}
|
||||
} else {
|
||||
writeStdout("ой сукаа я вахуе\n")
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
if (isFolder(target)) {
|
||||
target = target+"/"+source.split("/").reverse()[0]
|
||||
}
|
||||
|
||||
let content = readFile(source)
|
||||
writeFile(target, content)
|
||||
}
|
||||
|
||||
removeFile(source)
|
||||
|
||||
writeStdout(`все скопировано бро ${source} в ${target} скопировано спомощье команды CP (ЦП)\n`)
|
||||
|
||||
return 0
|
||||
}
|
12
app/putils/ls.js
Normal file
12
app/putils/ls.js
Normal file
@ -0,0 +1,12 @@
|
||||
async function main(args) {
|
||||
if (args.length < 2) {
|
||||
writeStdout(listFiles(".").map(o => {
|
||||
return (isFolder(o) ? "DIR " : "FILE") + " " + simplifyPath(o)
|
||||
}).join("\n")+"\n")
|
||||
} else {
|
||||
writeStdout(listFiles(args[1]).map(o => {
|
||||
return (isFolder(args[1]+"/"+o) ? "DIR " : "FILE") + " " + simplifyPath(args[1]+"/"+o)
|
||||
}).join("\n")+"\n")
|
||||
}
|
||||
return 0
|
||||
}
|
5
app/putils/mkdir.js
Normal file
5
app/putils/mkdir.js
Normal file
@ -0,0 +1,5 @@
|
||||
async function main(args) {
|
||||
createFolder(args[1])
|
||||
writeStdout(`папка создана ${args[1]}\n`)
|
||||
return 0
|
||||
}
|
55
app/putils/mv.js
Normal file
55
app/putils/mv.js
Normal file
@ -0,0 +1,55 @@
|
||||
async function main(args=["","",""]) {
|
||||
let source = simplifyPath(args[1])
|
||||
let target = simplifyPath(args[2])
|
||||
|
||||
if (!hasFile(args[1])) {
|
||||
writeStdout(`бро я б помог сделал что ты хочешь но сука нет такого файла бай бай\n`)
|
||||
return 1
|
||||
}
|
||||
|
||||
if (isFolder(source)) {
|
||||
if (!hasFile(target) || isFolder(target)) {
|
||||
let create_dirs = hasFile(target) ? [] : [target]
|
||||
let write_files = []
|
||||
|
||||
let recursive = (folder) => {
|
||||
for (const file of listFiles(folder)) {
|
||||
let path = folder+"/"+file
|
||||
if (isFolder(path)) {
|
||||
create_dirs.push(path)
|
||||
recursive(path)
|
||||
} else {
|
||||
write_files.push(path)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
recursive(source)
|
||||
|
||||
for (const dir of create_dirs) {
|
||||
createFolder(target + dir.slice(source.length))
|
||||
}
|
||||
|
||||
for (const file of write_files) {
|
||||
let path = target + file.slice(source.length)
|
||||
writeFile(path, readFile(file))
|
||||
}
|
||||
} else {
|
||||
writeStdout("как по твоему я должен блять переместить папку в файл ты ебнутый сука\n")
|
||||
return 1
|
||||
}
|
||||
} else {
|
||||
if (isFolder(target)) {
|
||||
target = target+"/"+source.split("/").reverse()[0]
|
||||
}
|
||||
|
||||
let content = readFile(source)
|
||||
writeFile(target, content)
|
||||
}
|
||||
|
||||
removeFile(source)
|
||||
|
||||
writeStdout(`все перемещено чо надо то есть ${source} в ${target} ну изи получается\n`)
|
||||
|
||||
return 0
|
||||
}
|
8
app/putils/package.json
Normal file
8
app/putils/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "putils",
|
||||
"version": "0.1.0",
|
||||
"description": "Poshliye Utiliti",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "bump.js", "cat.js", "cp.js", "ls.js", "mkdir.js", "mv.js", "rm.js" ],
|
||||
"configs": []
|
||||
}
|
9
app/putils/rm.js
Normal file
9
app/putils/rm.js
Normal file
@ -0,0 +1,9 @@
|
||||
async function main(args) {
|
||||
if (!hasFile(args[1])) {
|
||||
writeStdout(`я вахуе ну ты же знаешь что такого файла нет нахуй ты это делаешь\n`)
|
||||
return 1
|
||||
}
|
||||
removeFile(args[1])
|
||||
writeStdout(`ну все твой файл ${args[1]} удален ДОВОЛЕН ЧТО ТЫ СДЕЛАЛ?\n`)
|
||||
return 0
|
||||
}
|
8
app/reset/package.json
Normal file
8
app/reset/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "reset",
|
||||
"version": "0.1.0",
|
||||
"description": "Resets system to a newborn",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "reset.js" ],
|
||||
"configs": []
|
||||
}
|
18
app/reset/reset.js
Normal file
18
app/reset/reset.js
Normal file
@ -0,0 +1,18 @@
|
||||
async function main(args) {
|
||||
await writeStdout("Ты уверен, что хочешь стереть систему, и установить снова?? (y/n) > ")
|
||||
let confirm = (await readLine()).toLowerCase() == "y"
|
||||
if (confirm) {
|
||||
await new Promise(r => setTimeout(r, 100));
|
||||
await writeStdout("Прощай...")
|
||||
await new Promise(r => setTimeout(r, 2000));
|
||||
await resetSystem()
|
||||
document.location.reload()
|
||||
for (const c of Array.from("\nвелосипе")) {
|
||||
await writeStdout(c)
|
||||
await new Promise(r => setTimeout(r, 30));
|
||||
}
|
||||
await new Promise(r => setTimeout(r, 999999));
|
||||
}
|
||||
|
||||
return 0
|
||||
}
|
8
app/vget/package.json
Normal file
8
app/vget/package.json
Normal file
@ -0,0 +1,8 @@
|
||||
{
|
||||
"name": "vget",
|
||||
"version": "0.1.0",
|
||||
"description": "Vulgar get",
|
||||
"author": "MeexReay",
|
||||
"apps": [ "vget.js" ],
|
||||
"configs": []
|
||||
}
|
17
app/vget/vget.js
Normal file
17
app/vget/vget.js
Normal file
@ -0,0 +1,17 @@
|
||||
/*
|
||||
|
||||
VGet - Vulgar Get
|
||||
|
||||
*/
|
||||
|
||||
async function main(args) {
|
||||
if (args.length != 3) {
|
||||
writeStdout("vget <url> <path>\n")
|
||||
return 1
|
||||
}
|
||||
|
||||
writeFile(args[2], await (await fetch(args[0])).text())
|
||||
writeStdout("Файл "+args[1]+" вставлен внутрь пути "+args[2]+"\n")
|
||||
|
||||
return 0
|
||||
}
|
BIN
font/terminus.ttf
Normal file
BIN
font/terminus.ttf
Normal file
Binary file not shown.
77
index.html
Normal file
77
index.html
Normal file
@ -0,0 +1,77 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>PoshlostiOS</title>
|
||||
|
||||
<link rel="apple-touch-icon" sizes="180x180" href="/icon/apple-touch-icon.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="/icon/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="/icon/favicon-16x16.png">
|
||||
<link rel="manifest" href="/icon/site.webmanifest">
|
||||
|
||||
<style>
|
||||
@font-face {
|
||||
font-family: 'terminus';
|
||||
src: url('font/terminus.ttf'); /* Legacy iOS */
|
||||
}
|
||||
|
||||
:root {
|
||||
--BLACK: rgb(12,12,12);
|
||||
--DARK_BLUE: rgb(0,55,218);
|
||||
--DARK_GREEN: rgb(19,161,14);
|
||||
--DARK_CYAN: rgb(58,150,221);
|
||||
--DARK_RED: rgb(197,15,31);
|
||||
--DARK_MAGENTA: rgb(136,23,152);
|
||||
--DARK_YELLOW: rgb(193,156,0);
|
||||
--DARK_WHITE: rgb(204,204,204);
|
||||
--BRIGHT_BLACK: rgb(118,118,118);
|
||||
--BRIGHT_BLUE: rgb(59,120,255);
|
||||
--BRIGHT_GREEN: rgb(22,198,12);
|
||||
--BRIGHT_CYAN: rgb(97,214,214);
|
||||
--BRIGHT_RED: rgb(231,72,86);
|
||||
--BRIGHT_MAGENTA: rgb(180,0,158);
|
||||
--BRIGHT_YELLOW: rgb(249,241,165);
|
||||
--WHITE: rgb(242,242,242);
|
||||
}
|
||||
|
||||
* {
|
||||
font-family: "terminus";
|
||||
font-size: 20px
|
||||
}
|
||||
|
||||
body {
|
||||
background-color: var(--BLACK);
|
||||
color: var(--WHITE);
|
||||
/* overflow: hidden; */
|
||||
user-select: none;
|
||||
}
|
||||
|
||||
#cursor {
|
||||
position: absolute;
|
||||
}
|
||||
|
||||
#clipboard-collect {
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
left: 0;
|
||||
right: 0;
|
||||
}
|
||||
|
||||
#terminal {
|
||||
white-space: pre;
|
||||
width: 100%;
|
||||
display: block;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<span id="terminal"></span><span id="cursor">_<input type="text" id="clipboard-collect"></span>
|
||||
</body>
|
||||
|
||||
<script src="sys/terminal.js"></script>
|
||||
<script src="sys/fs.js"></script>
|
||||
<script src="sys/ppm.js"></script>
|
||||
<script src="sys/system.js"></script>
|
||||
</html>
|
223
sys/fs.js
Normal file
223
sys/fs.js
Normal file
@ -0,0 +1,223 @@
|
||||
var fs_mapping = {}
|
||||
|
||||
function saveMapping() {
|
||||
localStorage.setItem("fs_mapping", JSON.stringify(fs_mapping))
|
||||
}
|
||||
|
||||
function loadMapping() {
|
||||
if (localStorage.getItem("fs_mapping") == null) {
|
||||
fs_mapping = {}
|
||||
} else {
|
||||
fs_mapping = JSON.parse(localStorage.getItem("fs_mapping"))
|
||||
}
|
||||
}
|
||||
|
||||
loadMapping()
|
||||
|
||||
function getMappingCode(path) {
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (Object.keys(now).includes(part)) {
|
||||
if (index == parts.length-1) {
|
||||
return "file_"+now[part]
|
||||
} else {
|
||||
now = now[part]
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function createMappingCode(path) {
|
||||
if (path.length === 0) return null
|
||||
|
||||
let code = 0, i, chr
|
||||
|
||||
for (i = 0; i < path.length; i++) {
|
||||
chr = path.charCodeAt(i)
|
||||
code = ((code << 5) - code) + chr
|
||||
code |= 0
|
||||
}
|
||||
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (index == parts.length-1) {
|
||||
now[part] = code
|
||||
} else if (Object.keys(now).includes(part)) {
|
||||
now = now[part]
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
saveMapping()
|
||||
|
||||
return "file_"+code
|
||||
}
|
||||
|
||||
function createMappingFolder(path) {
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (index == parts.length-1) {
|
||||
now[part] = {}
|
||||
} else if (Object.keys(now).includes(part)) {
|
||||
now = now[part]
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
saveMapping()
|
||||
return null
|
||||
}
|
||||
|
||||
function listMappingFolder(path) {
|
||||
if (path == "/") return Object.keys(fs_mapping)
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (Object.keys(now).includes(part)) {
|
||||
if (index == parts.length-1) {
|
||||
return Object.keys(now[part])
|
||||
} else {
|
||||
now = now[part]
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function isMappingFolder(path) {
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (Object.keys(now).includes(part)) {
|
||||
if (index == parts.length-1) {
|
||||
return typeof now[part] === "object"
|
||||
} else {
|
||||
now = now[part]
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function removeMappingEntry(path) {
|
||||
let parts = (path.startsWith("/") ? path.slice(1) : path).split("/")
|
||||
let now = fs_mapping
|
||||
|
||||
let index = 0
|
||||
for (const part of parts) {
|
||||
if (Object.keys(now).includes(part)) {
|
||||
if (index == parts.length-1) {
|
||||
delete now[part]
|
||||
|
||||
saveMapping()
|
||||
} else {
|
||||
now = now[part]
|
||||
}
|
||||
} else {
|
||||
return null
|
||||
}
|
||||
index++
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
function readFile(path) {
|
||||
path = simplifyPath(path)
|
||||
return localStorage.getItem(getMappingCode(path))
|
||||
}
|
||||
|
||||
function writeFile(path, content) {
|
||||
path = simplifyPath(path)
|
||||
let code = getMappingCode(path)
|
||||
if (code == null) code = createMappingCode(path)
|
||||
localStorage.setItem(code, content)
|
||||
}
|
||||
|
||||
function hasFile(path) {
|
||||
path = simplifyPath(path)
|
||||
return getMappingCode(path) != null
|
||||
}
|
||||
|
||||
function listFiles(path) {
|
||||
path = simplifyPath(path)
|
||||
return listMappingFolder(path)
|
||||
}
|
||||
|
||||
function createFolder(path) {
|
||||
createMappingFolder(simplifyPath(path))
|
||||
}
|
||||
|
||||
function removeFile(path) {
|
||||
path = simplifyPath(path)
|
||||
if (!isFolder(path)) {
|
||||
localStorage.removeItem(getMappingCode(path))
|
||||
}
|
||||
removeMappingEntry(path)
|
||||
}
|
||||
|
||||
function isFolder(path) {
|
||||
path = simplifyPath(path)
|
||||
return isMappingFolder(path)
|
||||
}
|
||||
|
||||
function simplifyPath(path) {
|
||||
if (!path.startsWith("/")) path = cwd+"/" + path;
|
||||
|
||||
const segments = path.split('/');
|
||||
const stack = [];
|
||||
|
||||
for (let segment of segments) {
|
||||
if (segment === '' || segment === '.') {
|
||||
continue;
|
||||
} else if (segment === '..') {
|
||||
if (stack.length > 0) {
|
||||
stack.pop();
|
||||
}
|
||||
} else {
|
||||
stack.push(segment);
|
||||
}
|
||||
}
|
||||
|
||||
const simplifiedPath = '/' + stack.join('/');
|
||||
return simplifiedPath;
|
||||
}
|
||||
|
||||
function clearFileSystem() {
|
||||
let callback = (x) => {
|
||||
for (const o of Object.values(x)) {
|
||||
if (typeof o === "object") {
|
||||
callback(o)
|
||||
} else {
|
||||
localStorage.removeItem("file_"+o)
|
||||
}
|
||||
}
|
||||
}
|
||||
callback(fs_mapping)
|
||||
fs_mapping = {}
|
||||
saveMapping()
|
||||
}
|
128
sys/ppm.js
Normal file
128
sys/ppm.js
Normal file
@ -0,0 +1,128 @@
|
||||
async function fetchPackage(url) {
|
||||
try {
|
||||
return await fetchJson(url+"/package.json")
|
||||
} catch (error) {
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
async function getInstalledPackage(name) {
|
||||
if (!hasFile("/etc/ppm/"+name)) {
|
||||
return null
|
||||
}
|
||||
|
||||
return JSON.parse(readFile("/etc/ppm/"+name))
|
||||
}
|
||||
|
||||
async function listPackages() {
|
||||
let packages = []
|
||||
for (const name of listFiles("/etc/ppm")) {
|
||||
packages.push(JSON.parse(readFile("/etc/ppm/"+name)))
|
||||
}
|
||||
return packages
|
||||
}
|
||||
|
||||
async function fetchJson(url) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
try {
|
||||
return await fetch(url).then(o => o.json())
|
||||
} catch (error) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async function fetchText(url) {
|
||||
for (let i = 0; i < 10; i++) {
|
||||
try {
|
||||
return await fetch(url).then(o => o.text())
|
||||
} catch (error) {
|
||||
continue
|
||||
}
|
||||
}
|
||||
return null
|
||||
}
|
||||
|
||||
async function installPackage(url) {
|
||||
let package
|
||||
try {
|
||||
package = await fetch(url+"/package.json").then(o => o.json())
|
||||
} catch (error) {
|
||||
return 2
|
||||
}
|
||||
|
||||
if (!hasFile("/etc/ppm")) {
|
||||
createFolder("/etc/ppm")
|
||||
}
|
||||
|
||||
if (hasFile("/etc/ppm/"+package["name"])) {
|
||||
return 1
|
||||
}
|
||||
|
||||
if ("apps" in package) {
|
||||
for (const app of package.apps) {
|
||||
writeFile("/app/"+app, await fetchText(url+"/"+app))
|
||||
}
|
||||
}
|
||||
|
||||
if ("configs" in package) {
|
||||
for (const config of package.configs) {
|
||||
writeFile("/config/"+config, await fetchText(url+"/"+config))
|
||||
}
|
||||
}
|
||||
|
||||
writeFile("/etc/ppm/"+package["name"], JSON.stringify(package))
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
async function removePackage(name) {
|
||||
let package = await getInstalledPackage(name)
|
||||
|
||||
if (package == null) return false
|
||||
|
||||
if ("apps" in package) {
|
||||
for (const app of package.apps) {
|
||||
removeFile("/app/"+app)
|
||||
}
|
||||
}
|
||||
|
||||
if ("configs" in package) {
|
||||
for (const config of package.configs) {
|
||||
removeFile("/config/"+config)
|
||||
}
|
||||
}
|
||||
|
||||
removeFile("/etc/ppm/"+name)
|
||||
|
||||
return true
|
||||
}
|
||||
|
||||
async function updatePackage(name, url) {
|
||||
let package = await getInstalledPackage(name)
|
||||
|
||||
if (package == null) return 1
|
||||
|
||||
if ("apps" in package) {
|
||||
for (const app of package.apps) {
|
||||
removeFile("/app/"+app)
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
package = await fetch(url+"/package.json").then(o => o.json())
|
||||
} catch (error) {
|
||||
return 2
|
||||
}
|
||||
|
||||
if ("apps" in package) {
|
||||
for (const app of package.apps) {
|
||||
writeFile("/app/"+app, await fetchText(url+"/"+app))
|
||||
}
|
||||
}
|
||||
|
||||
writeFile("/etc/ppm/"+name, JSON.stringify(package))
|
||||
|
||||
return 0
|
||||
}
|
190
sys/system.js
Normal file
190
sys/system.js
Normal file
@ -0,0 +1,190 @@
|
||||
var cwd = "/home"
|
||||
|
||||
var stdout = ""
|
||||
var stdin = ""
|
||||
|
||||
var disable_stdin = true
|
||||
var silent_stdin = false
|
||||
|
||||
var processes = []
|
||||
|
||||
const RENDER_STDIN = 1
|
||||
const SILENT_STDIN = 2
|
||||
const DISABLE_STDIN = 3
|
||||
const ENABLE_STDIN = 4
|
||||
|
||||
async function readLine(on_key=(key, ctrl, alt, shift, content, pos) => [content, pos]) {
|
||||
setStdinFlag(ENABLE_STDIN)
|
||||
|
||||
let start_cursor_pos = getCursor()
|
||||
|
||||
let pos = 0
|
||||
let content = ""
|
||||
while (true) {
|
||||
let event = await pollStdinEvent()
|
||||
|
||||
if (event.type == "key") {
|
||||
if (event.key == "Backspace") {
|
||||
if (content.length >= 1) {
|
||||
content = content.substring(0, content.length-1)
|
||||
trimTerminal(1)
|
||||
}
|
||||
} else if (event.key == "ArrowLeft") {
|
||||
let cursor = getCursor()
|
||||
if (cursor[0] > start_cursor_pos[0]) {
|
||||
setCursor(cursor[0]-1, cursor[1])
|
||||
pos -= 1
|
||||
}
|
||||
} else if (event.key == "ArrowRight") {
|
||||
let cursor = getCursor()
|
||||
if (cursor[0] < start_cursor_pos[0] + content.length) {
|
||||
setCursor(cursor[0]+1, cursor[1])
|
||||
pos += 1
|
||||
}
|
||||
} else {
|
||||
let res = on_key(key, is_ctrl, is_alt, is_shift, content, pos)
|
||||
terminal_text = terminal_text.slice(0, terminal_text.length - content.length) + res[0]
|
||||
updateTerminal()
|
||||
setCursor(start_cursor_pos[0] + res[1], start_cursor_pos[1])
|
||||
content = res[0]
|
||||
pos = res[1]
|
||||
}
|
||||
|
||||
continue
|
||||
} else if (event.type == "char") {
|
||||
if (event.char == "\n") break
|
||||
|
||||
content = content.slice(0, pos) + event.char + content.slice(pos)
|
||||
pos += 1
|
||||
}
|
||||
}
|
||||
|
||||
setStdinFlag(DISABLE_STDIN)
|
||||
|
||||
return content
|
||||
}
|
||||
|
||||
async function pollStdinEvent() {
|
||||
let char = await readStdin()
|
||||
|
||||
if (char == "\r") {
|
||||
let key = ""
|
||||
char = await readStdin()
|
||||
while (char != "\r") {
|
||||
key += char
|
||||
char = await readStdin()
|
||||
}
|
||||
|
||||
let is_ctrl = key.charAt(0) == "1"
|
||||
let is_alt = key.charAt(1) == "1"
|
||||
let is_shift = key.charAt(2) == "1"
|
||||
key = key.slice(3)
|
||||
|
||||
return {
|
||||
"type": "key",
|
||||
"ctrl": is_ctrl,
|
||||
"alt": is_alt,
|
||||
"shift": is_shift,
|
||||
"key": key
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
"type": "char",
|
||||
"char": char
|
||||
}
|
||||
}
|
||||
|
||||
async function readStdin() {
|
||||
while (stdin.length == 0) {
|
||||
await new Promise(resolve => setTimeout(resolve, 10))
|
||||
}
|
||||
let was_stdin = stdin.charAt(0)
|
||||
stdin = stdin.slice(1)
|
||||
return was_stdin
|
||||
}
|
||||
|
||||
async function writeStdout(content) {
|
||||
stdout += content
|
||||
writeTerminal(content)
|
||||
}
|
||||
|
||||
function setStdinFlag(flag) {
|
||||
if (flag == 1) {
|
||||
silent_stdin = true
|
||||
} else if (flag == 2) {
|
||||
silent_stdin = false
|
||||
} else if (flag == 3) {
|
||||
disable_stdin = true
|
||||
} else if (flag == 4) {
|
||||
disable_stdin = false
|
||||
}
|
||||
}
|
||||
|
||||
function executeCommand(args, read=readStdin, write=writeStdout) {
|
||||
let id = new Date().getMilliseconds().toString()+(Math.random()*100)
|
||||
let func_content = readFile(args[0])
|
||||
if (func_content == null || !func_content.includes("function main")) return
|
||||
let func = new Function("args", "readStdin", "writeStdout", func_content+"\n\nreturn main(args)")
|
||||
let process = {
|
||||
"id": id,
|
||||
"name": args.join(" "),
|
||||
"promise": new Promise((resolve, reject) => {
|
||||
setTimeout(() => {
|
||||
try {
|
||||
resolve(func(args, read, write))
|
||||
} catch (e) {
|
||||
console.log(e)
|
||||
reject(e)
|
||||
}
|
||||
}, 0)
|
||||
}).then(o => {
|
||||
processes = processes.filter(x => x.id != id)
|
||||
return o
|
||||
})
|
||||
}
|
||||
processes.push(process)
|
||||
return process
|
||||
}
|
||||
|
||||
function loadApp(name) {
|
||||
fetch("app/"+name+".js")
|
||||
.then(o => o.text())
|
||||
.then(o => {
|
||||
writeFile("/app/"+name+".js", o)
|
||||
})
|
||||
}
|
||||
|
||||
function loadAppAndExecute(name) {
|
||||
fetch("app/"+name+".js")
|
||||
.then(o => o.text())
|
||||
.then(o => {
|
||||
writeFile("/app/"+name+".js", o)
|
||||
})
|
||||
}
|
||||
|
||||
async function resetSystem() {
|
||||
clearFileSystem()
|
||||
|
||||
createFolder("/")
|
||||
createFolder("/home")
|
||||
createFolder("/app")
|
||||
createFolder("/config")
|
||||
createFolder("/temp")
|
||||
createFolder("/etc")
|
||||
|
||||
await installPackage("app/hello")
|
||||
await installPackage("app/posh")
|
||||
await installPackage("app/ppm")
|
||||
await installPackage("app/putils")
|
||||
await installPackage("app/reset")
|
||||
await installPackage("app/vget")
|
||||
}
|
||||
|
||||
if (Object.keys(fs_mapping).length == 0) {
|
||||
resetSystem()
|
||||
}
|
||||
|
||||
executeCommand(["/app/posh.js"])
|
||||
|
||||
var start_date = new Date()
|
116
sys/terminal.js
Normal file
116
sys/terminal.js
Normal file
@ -0,0 +1,116 @@
|
||||
const CHAR_SIZE = [10, 22]
|
||||
const CURSOR_OFFSET = [10, 10]
|
||||
|
||||
var terminal = document.getElementById("terminal")
|
||||
var terminal_text = ""
|
||||
var last_stdin_length = 0
|
||||
|
||||
function writeTerminalAtCursor(content) {
|
||||
let cursor_index = getCursorIndex()
|
||||
terminal_text = terminal_text.slice(0, cursor_index) + content + terminal_text.slice(cursor_index)
|
||||
setCursor(cursor_pos[0]+1, cursor_pos[1])
|
||||
last_stdin_length += 1
|
||||
updateTerminalWOCursor()
|
||||
}
|
||||
|
||||
function writeTerminal(content) {
|
||||
terminal_text += content
|
||||
last_stdin_length = 0
|
||||
updateTerminal()
|
||||
}
|
||||
|
||||
function replaceTerminal(content) {
|
||||
terminal_text = content
|
||||
updateTerminal()
|
||||
}
|
||||
|
||||
function trimTerminal(length) {
|
||||
terminal_text = terminal_text.substring(0, terminal_text.length-length)
|
||||
updateTerminal()
|
||||
}
|
||||
|
||||
function clearTerminal() {
|
||||
terminal_text = ""
|
||||
updateTerminal()
|
||||
}
|
||||
|
||||
function updateTerminalWOCursor() {
|
||||
terminal.innerText = terminal_text
|
||||
}
|
||||
|
||||
function updateTerminal() {
|
||||
setCursor(
|
||||
terminal_text.split("\n").reverse()[0].length,
|
||||
terminal_text.split("\n").length-1
|
||||
)
|
||||
updateTerminalWOCursor()
|
||||
}
|
||||
|
||||
var cursor = document.getElementById("cursor")
|
||||
var cursor_pos = [0, 0]
|
||||
|
||||
function getCursorIndex() {
|
||||
let lines = terminal_text.split("\n")
|
||||
let index = 0
|
||||
for (let y = 0; y < lines.length; y++) {
|
||||
const line = lines[y];
|
||||
const length = line.length
|
||||
|
||||
if (y == cursor_pos[1]) {
|
||||
return index + cursor_pos[0]
|
||||
}
|
||||
|
||||
index += length + 1
|
||||
}
|
||||
return 0
|
||||
}
|
||||
|
||||
function getCursor() {
|
||||
return cursor_pos
|
||||
}
|
||||
|
||||
function setCursor(x, y) {
|
||||
cursor_pos = [x, y]
|
||||
updateCursor()
|
||||
}
|
||||
|
||||
function updateCursor() {
|
||||
cursor.style["top"] = cursor_pos[1] * CHAR_SIZE[1] + CURSOR_OFFSET[1] + "px"
|
||||
cursor.style["left"] = cursor_pos[0] * CHAR_SIZE[0] + CURSOR_OFFSET[0] + "px"
|
||||
cursor.scrollIntoView({behavior: "smooth", inline: "end"})
|
||||
}
|
||||
|
||||
document.onkeydown = (e) => {
|
||||
let key = e.key;
|
||||
if (!disable_stdin) {
|
||||
if (key == "Enter") {
|
||||
stdin += "\n"
|
||||
if (!silent_stdin) {
|
||||
writeTerminal("\n")
|
||||
}
|
||||
} else if (key.length == 1) {
|
||||
if (e.ctrlKey && key == "v") return
|
||||
stdin += key
|
||||
if (!silent_stdin) {
|
||||
writeTerminalAtCursor(key)
|
||||
}
|
||||
} else {
|
||||
stdin += "\r"+(e.ctrlKey ? "1" : "0")+(e.altKey ? "1" : "0")+(e.shiftKey ? "1" : "0")+e.key+"\r"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var clipboard_collect = document.getElementById("clipboard-collect")
|
||||
|
||||
setInterval(() => {
|
||||
clipboard_collect.focus()
|
||||
});
|
||||
|
||||
clipboard_collect.onpaste = (e) => {
|
||||
let paste = (e.clipboardData || window.clipboardData).getData("text");
|
||||
|
||||
if (paste != null) {
|
||||
stdin += paste.replace("\r", "")
|
||||
writeTerminal(paste)
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user