mirror of
https://github.com/MeexReay/poshlostios.git
synced 2025-06-24 02:22: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