diff --git a/cat.yarn b/cat.yarn index a143221..277e8be 100644 --- a/cat.yarn +++ b/cat.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"cat","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"cat.js":"%B/cat.js"}},"content":"{\"cat.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"program.autoOutput = false\\n\\nfor (let a of args) {\\n let file\\n try {\\n file = io.open(a)\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000)\\n }\\n if (file) {\\n const lines = file.lines()\\n for (let line of lines) {\\n io.output(\\\"%n\\\" + line)\\n display.print(line, itty.baseStyle, false)\\n }\\n }\\n}\\n \\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"cat","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"cat.js":"%B/cat.js"}},"content":"{\"cat.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"program.autoOutput = false\\n\\nfor (let a of args) {\\n let file\\n try {\\n file = io.open(a)\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000)\\n }\\n if (file) {\\n const lines = file.lines()\\n for (let line of lines) {\\n io.output(\\\"%n\\\" + line)\\n display.print(line, itty.baseStyle, false)\\n }\\n }\\n}\\n \\nquit()\"}}"} \ No newline at end of file diff --git a/clear.yarn b/clear.yarn index 15b1d6f..cf3e1df 100644 --- a/clear.yarn +++ b/clear.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"clear","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"clear.js":"%B/clear.js"}},"content":"{\"clear.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"display.clear(); quit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"clear","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"clear.js":"%B/clear.js"}},"content":"{\"clear.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"display.clear(); quit()\"}}"} \ No newline at end of file diff --git a/cp.yarn b/cp.yarn index 799eac1..ffb7173 100644 --- a/cp.yarn +++ b/cp.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"clear","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"clear.js":"%B/clear.js"}},"content":"{\"cp.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[0] && !args[1]) {\\n itty.display.print(\\\"Not enough arguments\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n itty.fs.copyNode(args[0], args[1])\\n} catch (e) {\\n itty.display.print(e[1] || \\\"Error copying node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"clear","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"clear.js":"%B/clear.js"}},"content":"{\"cp.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[0] && !args[1]) {\\n itty.display.print(\\\"Not enough arguments\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n itty.fs.copyNode(args[0], args[1])\\n} catch (e) {\\n itty.display.print(e[1] || \\\"Error copying node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file diff --git a/echo.yarn b/echo.yarn index 2e380c0..e17d900 100644 --- a/echo.yarn +++ b/echo.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"echo","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"echo.js":"%B/echo.js"}},"content":"{\"echo.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"let echo = pipe\\nif (!pipe)\\n echo = args.join(\\\" \\\")\\n\\ndisplay.print(echo, itty.baseStyle, false)\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"echo","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"echo.js":"%B/echo.js"}},"content":"{\"echo.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"let echo = pipe\\nif (!pipe)\\n echo = args.join(\\\" \\\")\\n\\ndisplay.print(echo, itty.baseStyle, false)\\nquit()\"}}"} \ No newline at end of file diff --git a/env.yarn b/env.yarn index 3b6723b..78d30da 100644 --- a/env.yarn +++ b/env.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"env","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"env.js":"%B/env.js"}},"content":"{\"env.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"const subcommand = args[0]\\nconst env = args[1]\\n\\nconst envtype = typeof itty.env[env]\\nlet value\\n\\nlet listing = false\\nlet listIndex = 0\\n\\nswitch(subcommand) {\\n case \\\"get\\\":\\n if (!env) {\\n display.print(\\\"No variable specified\\\")\\n quit()\\n }\\n display.print(JSON.stringify(itty.env[env]), getEnvStyle(envtype))\\n quit()\\n break\\n case \\\"set\\\":\\n if (!env) {\\n display.print(\\\"No variable specified\\\")\\n quit()\\n }\\n await parseValue()\\n if (itty.env[env] && typeof itty.env[env] !== typeof value) {\\n let r = await io.read(\\\"Mismatch between env type and provided value type. Continue? [y/N]: \\\")\\n if (r.length === 0 || r[0].toLowerCase() !== \\\"y\\\") {\\n display.print(\\\"Aborting...\\\")\\n quit()\\n }\\n }\\n itty.env[env] = value\\n quit()\\n break\\n case \\\"list\\\":\\n if (Object.keys(itty.env).length < itty.height - 4) {\\n for (let e in itty.env) {\\n display.buffer(e, getEnvStyle(typeof itty.env[e]))\\n display.buffer(\\\" = \\\", 0xe000)\\n display.print(JSON.stringify(itty.env[e]).replaceAll(\\\"%\\\", \\\"%%\\\"))\\n }\\n display.render()\\n quit()\\n } else {\\n program.enterFullscreen()\\n listing = true\\n onInput(\\\"\\\", {})\\n }\\n}\\n\\nfunction onInput(k) {\\n if (!listing)\\n return\\n\\n switch (k) {\\n case \\\"%^\\\":\\n listIndex = Math.max(listIndex - 1, 0)\\n break\\n case \\\"%v\\\":\\n listIndex = Math.min(listIndex + 1, Object.keys(itty.env).length - 1)\\n break\\n case \\\"%e\\\":\\n display.clear()\\n quit()\\n }\\n\\n display.clear()\\n for (let i = listIndex; i < itty.height - 1 + listIndex; i++) {\\n const e = Object.keys(itty.env)[i]\\n if (!e)\\n break\\n\\n display.buffer(e, getEnvStyle(typeof itty.env[e]))\\n display.buffer(\\\" = \\\", 0xe000)\\n display.buffer(JSON.stringify(itty.env[e]) + \\\"%n\\\")\\n }\\n itty.cursorY = itty.height - 1\\n display.write(\\\"Arrow Up/Down to scroll, Escape to quit\\\")\\n}\\n\\nasync function parseValue() {\\n let v = await io.read([[\\\"Value: \\\", 0xe000]])\\n v = v.replaceAll(\\\"%%\\\", \\\"%\\\")\\n\\n try {\\n v = JSON.parse(v)\\n } catch (e) {\\n try {\\n v = JSON.parse('\\\"' + v + '\\\"')\\n } catch (e) {\\n throw [1, \\\"Cannot parse value\\\"]\\n }\\n }\\n value = v\\n}\\n \\nfunction getEnvStyle(type) {\\n let style = 0xf000\\n switch(type) {\\n case \\\"object\\\":\\n style = 0x4000\\n break\\n case \\\"string\\\":\\n style = 0x6000\\n break\\n case \\\"number\\\":\\n style = 0x5000\\n break\\n case \\\"boolean\\\":\\n style = 0xa000\\n break\\n }\\n return style\\n}\\n\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"env","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"env.js":"%B/env.js"}},"content":"{\"env.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"const subcommand = args[0]\\nconst env = args[1]\\n\\nconst envtype = typeof itty.env[env]\\nlet value\\n\\nlet listing = false\\nlet listIndex = 0\\n\\nswitch(subcommand) {\\n case \\\"get\\\":\\n if (!env) {\\n display.print(\\\"No variable specified\\\")\\n quit()\\n }\\n display.print(JSON.stringify(itty.env[env]), getEnvStyle(envtype))\\n quit()\\n break\\n case \\\"set\\\":\\n if (!env) {\\n display.print(\\\"No variable specified\\\")\\n quit()\\n }\\n await parseValue()\\n if (itty.env[env] && typeof itty.env[env] !== typeof value) {\\n let r = await io.read(\\\"Mismatch between env type and provided value type. Continue? [y/N]: \\\")\\n if (r.length === 0 || r[0].toLowerCase() !== \\\"y\\\") {\\n display.print(\\\"Aborting...\\\")\\n quit()\\n }\\n }\\n itty.env[env] = value\\n quit()\\n break\\n case \\\"list\\\":\\n if (Object.keys(itty.env).length < itty.height - 4) {\\n for (let e in itty.env) {\\n display.buffer(e, getEnvStyle(typeof itty.env[e]))\\n display.buffer(\\\" = \\\", 0xe000)\\n display.print(JSON.stringify(itty.env[e]).replaceAll(\\\"%\\\", \\\"%%\\\"))\\n }\\n display.render()\\n quit()\\n } else {\\n program.enterFullscreen()\\n listing = true\\n onInput(\\\"\\\", {})\\n }\\n}\\n\\nfunction onInput(k) {\\n if (!listing)\\n return\\n\\n switch (k) {\\n case \\\"%^\\\":\\n listIndex = Math.max(listIndex - 1, 0)\\n break\\n case \\\"%v\\\":\\n listIndex = Math.min(listIndex + 1, Object.keys(itty.env).length - 1)\\n break\\n case \\\"%e\\\":\\n display.clear()\\n quit()\\n }\\n\\n display.clear()\\n for (let i = listIndex; i < itty.height - 1 + listIndex; i++) {\\n const e = Object.keys(itty.env)[i]\\n if (!e)\\n break\\n\\n display.buffer(e, getEnvStyle(typeof itty.env[e]))\\n display.buffer(\\\" = \\\", 0xe000)\\n display.buffer(JSON.stringify(itty.env[e]) + \\\"%n\\\")\\n }\\n itty.cursorY = itty.height - 1\\n display.write(\\\"Arrow Up/Down to scroll, Escape to quit\\\")\\n}\\n\\nasync function parseValue() {\\n let v = await io.read([[\\\"Value: \\\", 0xe000]])\\n v = v.replaceAll(\\\"%%\\\", \\\"%\\\")\\n\\n try {\\n v = JSON.parse(v)\\n } catch (e) {\\n try {\\n v = JSON.parse('\\\"' + v + '\\\"')\\n } catch (e) {\\n throw [1, \\\"Cannot parse value\\\"]\\n }\\n }\\n value = v\\n}\\n \\nfunction getEnvStyle(type) {\\n let style = 0xf000\\n switch(type) {\\n case \\\"object\\\":\\n style = 0x4000\\n break\\n case \\\"string\\\":\\n style = 0x6000\\n break\\n case \\\"number\\\":\\n style = 0x5000\\n break\\n case \\\"boolean\\\":\\n style = 0xa000\\n break\\n }\\n return style\\n}\\n\\nquit()\"}}"} \ No newline at end of file diff --git a/info.yarn b/info.yarn index ff7672b..ae2c2ad 100644 --- a/info.yarn +++ b/info.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"info","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"info.js":"%B/info.js"}},"content":"{\"info.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"display.buffer(`Itty version: v${itty.version[0]}.${itty.version[1]}${itty.version[2] ? \\\".\\\" + itty.version[2] : \\\"\\\"} ${itty.version[3] || \\\"\\\"}%nRoot FS: ${itty.disk.version}`, 0x4000)\\ndisplay.buffer(\\\"%n%nDisplay dimensions: \\\", 0x7000)\\ndisplay.buffer(itty.width + \\\"x\\\" + itty.height + \\\"%n%n\\\", 0x6000)\\nfor (let i=0; i < 8; i++) {\\n display.buffer(\\\" \\\", 0x0100 * i)\\n}\\nitty.cursorY++\\nitty.cursorX = 0\\nfor (let i=8; i < 16; i++) {\\n display.buffer(\\\" \\\", 0x0100 * i)\\n}\\n\\ndisplay.buffer(\\\"%n%nITTY: Incredibly Tiny Terminal, Yay!\\\", 0x4041)\\ndisplay.buffer(\\\" by \\\", 0x7041)\\ndisplay.buffer(\\\"Magdalunaa\\\", 0x6051)\\nstyle.setAttribute(1, {_link: \\\"https://codeberg.org/Magdalunaa/itty\\\", style: \\\"cursor: pointer; text-decoration-color: var(--itty-c-4)\\\"})\\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"info","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"info.js":"%B/info.js"}},"content":"{\"info.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"display.buffer(`Itty version: v${itty.version[0]}.${itty.version[1]}${itty.version[2] ? \\\".\\\" + itty.version[2] : \\\"\\\"} ${itty.version[3] || \\\"\\\"}%nRoot FS: ${itty.disk.version}`, 0x4000)\\ndisplay.buffer(\\\"%n%nDisplay dimensions: \\\", 0x7000)\\ndisplay.buffer(itty.width + \\\"x\\\" + itty.height + \\\"%n%n\\\", 0x6000)\\nfor (let i=0; i < 8; i++) {\\n display.buffer(\\\" \\\", 0x0100 * i)\\n}\\nitty.cursorY++\\nitty.cursorX = 0\\nfor (let i=8; i < 16; i++) {\\n display.buffer(\\\" \\\", 0x0100 * i)\\n}\\n\\ndisplay.buffer(\\\"%n%nITTY: Incredibly Tiny Terminal, Yay!\\\", 0x4041)\\ndisplay.buffer(\\\" by \\\", 0x7041)\\ndisplay.buffer(\\\"Magdalunaa\\\", 0x6051)\\nstyle.setAttribute(1, {_link: \\\"https://codeberg.org/Magdalunaa/itty\\\", style: \\\"cursor: pointer; text-decoration-color: var(--itty-c-4)\\\"})\\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file diff --git a/loader.yarn b/loader.yarn index 3c64172..980f9ec 100644 --- a/loader.yarn +++ b/loader.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"loader","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"loader.js":"%B/loader.js"}},"content":"{\"loader.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[1]) {\\n display.print(\\\"Not enough arguments\\\")\\n quit()\\n}\\n\\nconst command = args[0]\\nargs.splice(0, 1)\\nconst mountpoint = args.join(\\\" \\\")\\nconst node = fs.getNode(mountpoint)\\nlet content\\n\\nswitch(command) {\\n case \\\"save\\\":\\n case \\\"download\\\":\\n content = fs.export(node)\\n\\n const blob = new Blob([content], { type: \\\"text/plain\\\" })\\n const url = URL.createObjectURL(blob)\\n\\n const a = document.createElement(\\\"a\\\")\\n a.href = url\\n a.download = node.name\\n a.style.display = \\\"none\\\"\\n\\n document.body.appendChild(a)\\n a.click()\\n document.body.removeChild(a)\\n\\n URL.revokeObjectURL(url)\\n break\\n case \\\"load\\\":\\n case \\\"upload\\\":\\n content = await getFile()\\n await fs.import(content.text, mountpoint)\\n display.print(\\\"Disk loaded successfully\\\", 0x3000)\\n}\\n\\nquit()\\n\\nfunction getFile() {\\n return new Promise(resolve => {\\n const input = document.createElement(\\\"input\\\")\\n input.type = \\\"file\\\"\\n input.accept = \\\"*/*\\\"\\n input.style.display = \\\"none\\\"\\n\\n document.body.appendChild(input)\\n\\n input.onchange = async () => {\\n const file = input.files[0]\\n const text = await file.text();\\n document.body.removeChild(input)\\n resolve({ file, text })\\n }\\n\\n input.click()\\n })\\n}\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"loader","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"loader.js":"%B/loader.js"}},"content":"{\"loader.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[1]) {\\n display.print(\\\"Not enough arguments\\\")\\n quit()\\n}\\n\\nconst command = args[0]\\nargs.splice(0, 1)\\nconst mountpoint = args.join(\\\" \\\")\\nconst node = fs.getNode(mountpoint)\\nlet content\\n\\nswitch(command) {\\n case \\\"save\\\":\\n case \\\"download\\\":\\n content = fs.export(node)\\n\\n const blob = new Blob([content], { type: \\\"text/plain\\\" })\\n const url = URL.createObjectURL(blob)\\n\\n const a = document.createElement(\\\"a\\\")\\n a.href = url\\n a.download = node.name\\n a.style.display = \\\"none\\\"\\n\\n document.body.appendChild(a)\\n a.click()\\n document.body.removeChild(a)\\n\\n URL.revokeObjectURL(url)\\n break\\n case \\\"load\\\":\\n case \\\"upload\\\":\\n content = await getFile()\\n await fs.import(content.text, mountpoint)\\n display.print(\\\"Disk loaded successfully\\\", 0x3000)\\n}\\n\\nquit()\\n\\nfunction getFile() {\\n return new Promise(resolve => {\\n const input = document.createElement(\\\"input\\\")\\n input.type = \\\"file\\\"\\n input.accept = \\\"*/*\\\"\\n input.style.display = \\\"none\\\"\\n\\n document.body.appendChild(input)\\n\\n input.onchange = async () => {\\n const file = input.files[0]\\n const text = await file.text();\\n document.body.removeChild(input)\\n resolve({ file, text })\\n }\\n\\n input.click()\\n })\\n}\"}}"} \ No newline at end of file diff --git a/ls.yarn b/ls.yarn index ad63a72..a8ff0f1 100644 --- a/ls.yarn +++ b/ls.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"ls","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"ls.js":"%B/ls.js"}},"content":"{\"ls.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"// get flags\\nlet flags = {}\\nlet dir = \\\".\\\"\\nfor (let i=0; i < args.length; i++) {\\n if (args[i][0] === \\\"-\\\") {\\n if (args[i].indexOf(\\\"l\\\") !== -1)\\n flags.l = true\\n if (args[i].indexOf(\\\"a\\\") !== -1)\\n flags.a = true\\n } else {\\n dir = args[i]\\n break\\n }\\n}\\n\\n// get node\\nlet node\\ntry {\\n node = fs.getNode(dir)\\n} catch (e) {\\n display.print(\\\"Not a directory\\\")\\n quit()\\n}\\n\\nif (!node || node.mode !== \\\"d\\\") {\\n display.print(\\\"Not a directory\\\")\\n quit()\\n}\\n\\nlet empty = true\\nfor (let n of fs.listDir(node)) {\\n if (n.name[0] === \\\".\\\" && !flags.a)\\n continue\\n\\n empty = false\\n\\n let style = 0x7000\\n if (n.mode === \\\"d\\\")\\n style = 0x5000\\n\\n if (n.protected)\\n style += 0x0020\\n\\n if (itty.cursorX + n.name.length >= itty.width) {\\n itty.cursorX = 0\\n itty.cursorY++\\n }\\n\\n while (itty.cursorY >= itty.height)\\n display.lift()\\n\\n if (!flags.l) {\\n display.buffer(n.name + \\\" \\\", style)\\n } else {\\n display.buffer(n.mode + \\\" \\\", 0xc000)\\n display.buffer(n.name, style)\\n display.buffer(n.protected ? \\\" (protected)%n\\\" : \\\"%n\\\", 0xf000)\\n }\\n}\\n\\nif (empty)\\n display.print(\\\"Directory is empty\\\", 0xf000)\\n\\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"ls","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"ls.js":"%B/ls.js"}},"content":"{\"ls.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"// get flags\\nlet flags = {}\\nlet dir = \\\".\\\"\\nfor (let i=0; i < args.length; i++) {\\n if (args[i][0] === \\\"-\\\") {\\n if (args[i].indexOf(\\\"l\\\") !== -1)\\n flags.l = true\\n if (args[i].indexOf(\\\"a\\\") !== -1)\\n flags.a = true\\n } else {\\n dir = args[i]\\n break\\n }\\n}\\n\\n// get node\\nlet node\\ntry {\\n node = fs.getNode(dir)\\n} catch (e) {\\n display.print(\\\"Not a directory\\\")\\n quit()\\n}\\n\\nif (!node || node.mode !== \\\"d\\\") {\\n display.print(\\\"Not a directory\\\")\\n quit()\\n}\\n\\nlet empty = true\\nfor (let n of fs.listDir(node)) {\\n if (n.name[0] === \\\".\\\" && !flags.a)\\n continue\\n\\n empty = false\\n\\n let style = 0x7000\\n if (n.mode === \\\"d\\\")\\n style = 0x5000\\n\\n if (n.protected)\\n style += 0x0020\\n\\n if (itty.cursorX + n.name.length >= itty.width) {\\n itty.cursorX = 0\\n itty.cursorY++\\n }\\n\\n while (itty.cursorY >= itty.height)\\n display.lift()\\n\\n if (!flags.l) {\\n display.buffer(n.name + \\\" \\\", style)\\n } else {\\n display.buffer(n.mode + \\\" \\\", 0xc000)\\n display.buffer(n.name, style)\\n display.buffer(n.protected ? \\\" (protected)%n\\\" : \\\"%n\\\", 0xf000)\\n }\\n}\\n\\nif (empty)\\n display.print(\\\"Directory is empty\\\", 0xf000)\\n\\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file diff --git a/miss.yarn b/miss.yarn index 399012f..f5e021d 100644 --- a/miss.yarn +++ b/miss.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"miss","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"miss.js":"%B/miss.js"}},"content":"{\"miss.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\" // check if there is a config file\\nlet config = {}\\n\\nif (fs.getNode(fs.resolve(itty.env.dir_conf || \\\"/conf/\\\") + \\\"miss.conf\\\")) {\\n try {\\n const configFile = io.open(fs.resolve(itty.env.dir_conf || \\\"/conf/\\\") + \\\"miss.conf\\\")\\n config = configFile.read()\\n config = JSON.parse(config)\\n } catch (e) {\\n io.error([1, \\\"Error parsing config\\\"])\\n config = {}\\n }\\n}\\n\\nlet history = []\\nlet historyIndex = 0\\n\\nfunction onInput(key) {\\n switch (key) {\\n case \\\"%^\\\":\\n historyIndex = Math.max(historyIndex - 1, 0)\\n if (history[historyIndex]) {\\n program.read.input = history[historyIndex]\\n program.read.cursor = program.read.input.length\\n }\\n break\\n case \\\"%v\\\":\\n historyIndex = Math.min(historyIndex + 1, history.length)\\n if (history[historyIndex]) {\\n program.read.input = history[historyIndex]\\n program.read.cursor = program.read.input.length\\n } else if (historyIndex === history.length) {\\n program.read.input = \\\"\\\"\\n program.read.cursor = 0\\n }\\n break\\n }\\n}\\n\\nlet running = false\\n// this runs on every new line\\nasync function line() {\\n // promt! %D gets replaced by the active dir\\n const prompt = config.prompt || [[\\\"%D\\\", 0xc000], [\\\" > \\\", 0xd000]]\\n\\n for (let p of prompt)\\n p[0] = p[0].replace(/%D/g, program.currentDir)\\n\\n // parse arguments\\n let command = await io.read(prompt)\\n if (command !== \\\"\\\" && command !== history[history.length - 1]) {\\n history.push(command)\\n historyIndex = history.length\\n }\\n command = command.replace(/%%/g, \\\"%\\\")\\n let args = command.match(/\\\"([^\\\"%]*(%.[^\\\"%]*)*)\\\"|'([^'%]*(%.[^'%]*)*)'|\\\\S+/g)\\n\\n if (args) {\\n for (let i=0; i < args.length; i++) {\\n args[i] = args[i].replace(/^'(.*)'$|^\\\"(.*)\\\"$/, \\\"$1$2\\\")\\n args[i] = args[i].replace(/%(['\\\"])/g, \\\"$1\\\")\\n }\\n\\n // split into multiple commands\\n const commands = []\\n let redir\\n let c = []\\n for (let a of args) {\\n if (a !== \\\"|\\\") {\\n c.push(a)\\n } else {\\n commands.push(c.slice())\\n c = []\\n }\\n }\\n commands.push(c)\\n\\n let redirIndex = commands[commands.length - 1].indexOf(\\\">\\\")\\n if (redirIndex !== -1) {\\n redir = commands[commands.length - 1][redirIndex + 1]\\n commands[commands.length - 1] = commands[commands.length - 1].slice(0, redirIndex)\\n }\\n\\n running = true\\n let output = \\\"\\\"\\n for (let c = 0; c < commands.length; c++) {\\n const hidden = (c < commands.length - 1 || redir ? true : false)\\n output = await run(commands[c], output, hidden)\\n }\\n \\n if (redir) {\\n let file\\n try {\\n file = io.open(redir, \\\"a\\\")\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000) \\n }\\n if (file) {\\n file.write(output)\\n try {\\n file.writeOut()\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000) \\n }\\n }\\n }\\n\\n running = false\\n \\n if (itty.cursorX !== 0)\\n itty.cursorY++\\n\\n line()\\n } else {\\n line()\\n }\\n}\\n\\n// attempt to run autorun functions!\\nif (program.uid === 0) {\\n for (let a of [\\\"/autorun\\\", \\\"/autorun.js\\\", \\\"/.autorun\\\", \\\"/.autorun.js\\\"]) {\\n try {\\n exec.runProgram(a, [], \\\"\\\", false)\\n } catch {}\\n }\\n}\\n\\nline()\\n\\nasync function run(arg, input, hidden) {\\n const program = arg[0]\\n if (arg.length > 1)\\n arg.splice(0, 1)\\n else\\n arg = []\\n let file = null\\n\\n switch (program) {\\n // built in \\\"programs\\\"\\n case \\\"cd\\\":\\n try {\\n fs.changeDir(arg[0] || itty.env.home)\\n } catch (e) {\\n display.print(\\\"Not a directory\\\")\\n }\\n break\\n case \\\"exit\\\":\\n quit()\\n display.print(\\\"Cannot quit init process\\\", 0xf000)\\n return\\n break\\n // otherwise, call\\n default:\\n let output\\n try {\\n output = await exec.runProgram(program, arg, input, hidden)\\n } catch (e) {\\n if (e[0] !== 0) {\\n if (e[0] === -1 && e[1] === \\\"Cannot find program file\\\") {\\n display.print(`${program}: command not found.`, 0x2000)\\n return\\n } else\\n display.print(\\\"Error running program\\\", 0x9000)\\n }\\n }\\n\\n return output\\n }\\n}\\n\\nfunction onReturn() {\\n if (running)\\n return\\n\\n program.visible = true\\n program.focused = true\\n historyIndex = history.length\\n if (itty.cursorX !== 0)\\n itty.cursorY++\\n onError()\\n}\\n\\nfunction onError() {\\n if (program.visible) {\\n for (let e of io.getErrors()) {\\n display.write(`[${e[0]}] `, 0x9010)\\n display.print(e[1] || \\\"\\\")\\n }\\n }\\n}\\n\\nfunction onResize() {\\n if (program.focused) {\\n program.read.line = 0\\n display.clear()\\n }\\n}\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"miss","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"miss.js":"%B/miss.js"}},"content":"{\"miss.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\" // check if there is a config file\\nlet config = {}\\n\\nif (fs.getNode(fs.resolve(itty.env.dir_conf || \\\"/conf/\\\") + \\\"miss.conf\\\")) {\\n try {\\n const configFile = io.open(fs.resolve(itty.env.dir_conf || \\\"/conf/\\\") + \\\"miss.conf\\\")\\n config = configFile.read()\\n config = JSON.parse(config)\\n } catch (e) {\\n io.error([1, \\\"Error parsing config\\\"])\\n config = {}\\n }\\n}\\n\\nlet history = []\\nlet historyIndex = 0\\n\\nfunction onInput(key) {\\n switch (key) {\\n case \\\"%^\\\":\\n historyIndex = Math.max(historyIndex - 1, 0)\\n if (history[historyIndex]) {\\n program.read.input = history[historyIndex]\\n program.read.cursor = program.read.input.length\\n }\\n break\\n case \\\"%v\\\":\\n historyIndex = Math.min(historyIndex + 1, history.length)\\n if (history[historyIndex]) {\\n program.read.input = history[historyIndex]\\n program.read.cursor = program.read.input.length\\n } else if (historyIndex === history.length) {\\n program.read.input = \\\"\\\"\\n program.read.cursor = 0\\n }\\n break\\n }\\n}\\n\\nlet running = false\\n// this runs on every new line\\nasync function line() {\\n // promt! %D gets replaced by the active dir\\n const prompt = config.prompt || [[\\\"%D\\\", 0xc000], [\\\" > \\\", 0xd000]]\\n\\n for (let p of prompt)\\n p[0] = p[0].replace(/%D/g, program.currentDir)\\n\\n // parse arguments\\n let command = await io.read(prompt)\\n if (command !== \\\"\\\" && command !== history[history.length - 1]) {\\n history.push(command)\\n historyIndex = history.length\\n }\\n command = command.replace(/%%/g, \\\"%\\\")\\n let args = command.match(/\\\"([^\\\"%]*(%.[^\\\"%]*)*)\\\"|'([^'%]*(%.[^'%]*)*)'|\\\\S+/g)\\n\\n if (args) {\\n for (let i=0; i < args.length; i++) {\\n args[i] = args[i].replace(/^'(.*)'$|^\\\"(.*)\\\"$/, \\\"$1$2\\\")\\n args[i] = args[i].replace(/%(['\\\"])/g, \\\"$1\\\")\\n }\\n\\n // split into multiple commands\\n const commands = []\\n let redir\\n let c = []\\n for (let a of args) {\\n if (a !== \\\"|\\\") {\\n c.push(a)\\n } else {\\n commands.push(c.slice())\\n c = []\\n }\\n }\\n commands.push(c)\\n\\n let redirIndex = commands[commands.length - 1].indexOf(\\\">\\\")\\n if (redirIndex !== -1) {\\n redir = commands[commands.length - 1][redirIndex + 1]\\n commands[commands.length - 1] = commands[commands.length - 1].slice(0, redirIndex)\\n }\\n\\n running = true\\n let output = \\\"\\\"\\n for (let c = 0; c < commands.length; c++) {\\n const hidden = (c < commands.length - 1 || redir ? true : false)\\n output = await run(commands[c], output, hidden)\\n }\\n \\n if (redir) {\\n let file\\n try {\\n file = io.open(redir, \\\"a\\\")\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000) \\n }\\n if (file) {\\n file.write(output)\\n try {\\n file.writeOut()\\n } catch (e) {\\n display.print(\\\"Cannot open file\\\", 0x9000) \\n }\\n }\\n }\\n\\n running = false\\n \\n if (itty.cursorX !== 0)\\n itty.cursorY++\\n\\n line()\\n } else {\\n line()\\n }\\n}\\n\\n// attempt to run autorun functions!\\nif (program.uid === 0) {\\n for (let a of [\\\"/autorun\\\", \\\"/autorun.js\\\", \\\"/.autorun\\\", \\\"/.autorun.js\\\"]) {\\n try {\\n exec.runProgram(a, [], \\\"\\\", false)\\n } catch {}\\n }\\n}\\n\\nline()\\n\\nasync function run(arg, input, hidden) {\\n const program = arg[0]\\n if (arg.length > 1)\\n arg.splice(0, 1)\\n else\\n arg = []\\n let file = null\\n\\n switch (program) {\\n // built in \\\"programs\\\"\\n case \\\"cd\\\":\\n try {\\n fs.changeDir(arg[0] || itty.env.home)\\n } catch (e) {\\n display.print(\\\"Not a directory\\\")\\n }\\n break\\n case \\\"exit\\\":\\n quit()\\n display.print(\\\"Cannot quit init process\\\", 0xf000)\\n return\\n break\\n // otherwise, call\\n default:\\n let output\\n try {\\n output = await exec.runProgram(program, arg, input, hidden)\\n } catch (e) {\\n if (e[0] !== 0) {\\n if (e[0] === -1 && e[1] === \\\"Cannot find program file\\\") {\\n display.print(`${program}: command not found.`, 0x2000)\\n return\\n } else\\n display.print(\\\"Error running program\\\", 0x9000)\\n }\\n }\\n\\n return output\\n }\\n}\\n\\nfunction onReturn() {\\n if (running)\\n return\\n\\n program.visible = true\\n program.focused = true\\n historyIndex = history.length\\n if (itty.cursorX !== 0)\\n itty.cursorY++\\n onError()\\n}\\n\\nfunction onError() {\\n if (program.visible) {\\n for (let e of io.getErrors()) {\\n display.write(`[${e[0]}] `, 0x9010)\\n display.print(e[1] || \\\"\\\")\\n }\\n }\\n}\\n\\nfunction onResize() {\\n if (program.focused) {\\n program.read.line = 0\\n display.clear()\\n }\\n}\"}}"} \ No newline at end of file diff --git a/mkdir.yarn b/mkdir.yarn index c140c66..4b58a19 100644 --- a/mkdir.yarn +++ b/mkdir.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"mkdir","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"mkdir.js":"%B/mkdir.js"}},"content":"{\"mkdir.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.makeDir(args[0])\\n} catch (e) {\\n display.print(\\\"Error creating directory\\\", 0x1000)\\n}\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"mkdir","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"mkdir.js":"%B/mkdir.js"}},"content":"{\"mkdir.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.makeDir(args[0])\\n} catch (e) {\\n display.print(\\\"Error creating directory\\\", 0x1000)\\n}\\nquit()\"}}"} \ No newline at end of file diff --git a/mrrp.yarn b/mrrp.yarn index ba05e21..55e888d 100644 --- a/mrrp.yarn +++ b/mrrp.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"mrrp","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"mrrp.js":"%B/mrrp.js"}},"content":"{\"mrrp.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"let yarnball\\nlet repoNode = fs.getNode(\\\"/itty/repos.json\\\")\\nlet repoList = JSON.parse(repoNode.content)\\nlet pkgList\\nlet updateList = []\\nlet world = io.flines(fs.getNode(\\\"/itty/world\\\")).filter(Boolean)\\nlet unwantedPkgs\\n\\n// we use some env vars, parse them\\nconst dirs = {\\n bin: fs.resolve(itty.env.dir_bin).slice(0, -1) || \\\"/itty/bin\\\",\\n docs: fs.resolve(itty.env.dir_docs).slice(0, -1) || \\\"/itty/docs\\\",\\n conf: fs.resolve(itty.env.dir_conf) + \\\"examples\\\" || \\\"/conf/examples\\\"\\n}\\n\\n// cache repo indexes, so querying and updating is faster\\nlet repoCache = fs.getNode(\\\"/.tmp/mrrp/repocache\\\")\\nif (!repoCache) {\\n fs.makeDir(\\\"/.tmp/mrrp/\\\")\\n fs.makeNode(\\\"/.tmp/mrrp/repocache\\\", \\\"f\\\")\\n await refreshCache()\\n} else {\\n repoCache = JSON.parse(repoCache.content) \\n}\\n\\n// refresh the repo cache!\\nasync function refreshCache() {\\n repoCache = fs.getNode(\\\"/.tmp/mrrp/repocache\\\")\\n const list = {}\\n for (let r of Object.entries(repoList)) {\\n let rj\\n try {\\n rj = await fetch(r[1].url + \\\"repo.json\\\")\\n rj = await rj.json()\\n } catch {\\n display.print(\\\"Cannot fetch repository info for \\\" + r[0], 0x9000)\\n continue\\n }\\n rj.url = r[1].url\\n list[r[0]] = rj\\n }\\n repoCache.content = JSON.stringify(list)\\n repoCache = list\\n}\\n\\n// confirmation as to whether to do things\\nasync function ask(message) {\\n const res = await io.read([[message + \\\" [y/N]: \\\"]])\\n\\n if (res.toLowerCase() !== \\\"y\\\" && res.toLowerCase() !== \\\"yes\\\") {\\n display.print(\\\"Aborting...\\\", 0x9000)\\n return false\\n }\\n\\n display.print(\\\"Proceeding...\\\", 0x3000)\\n return true\\n}\\n\\n// install a program\\nasync function install(yarnball, reponame, interactive = true, wanted) {\\n wanted = wanted || world.includes(yarnball.metadata.name)\\n\\n const listNode = fs.getNode(\\\"/itty/packages.json\\\")\\n let list = JSON.parse(listNode.content)\\n\\n // substitute %B, %C and %D in paths with env vars\\n for (let path of Object.keys(yarnball.metadata.paths)) {\\n let p = yarnball.metadata.paths[path]\\n p = p.replaceAll(\\\"%B\\\", dirs.bin)\\n p = p.replaceAll(\\\"%D\\\", dirs.docs)\\n p = p.replaceAll(\\\"%C\\\", dirs.conf)\\n yarnball.metadata.paths[path] = p\\n }\\n\\n // ask the user!\\n if (interactive) {\\n const v = yarnball.metadata.version\\n display.print(\\\"Installing \\\" + yarnball.metadata.name + \\\" version \\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" from \\\" + reponame, 0x5000)\\n display.print(\\\"Warning: this will affect the following path(s):\\\", 0x2000)\\n for (let path in yarnball.metadata.paths) {\\n display.print(yarnball.metadata.paths[path], 0x2000)\\n }\\n if (yarnball.metadata.dependencies.length)\\n display.print(\\\"The following dependencies also need to be installed:\\\", 0x6000)\\n for (let d of yarnball.metadata.dependencies) {\\n if (!list[d])\\n display.print(d, 0x6000)\\n }\\n if (!await ask(\\\"Proceed?\\\"))\\n return\\n }\\n\\n // uninstall if already installed\\n if (list[yarnball.metadata.name])\\n await uninstall(yarnball.metadata.name, false)\\n\\n // unspool the yarnball\\n fs.removeNode(\\\"/.tmp/mrrp/x\\\")\\n fs.makeDir(\\\"/.tmp/mrrp/x\\\")\\n const node = fs.getNode(\\\"/.tmp/mrrp/x\\\")\\n let content\\n\\n try {\\n content = JSON.parse(yarnball.content)\\n } catch {\\n io.error([5, \\\"Cannot parse yarnball\\\"])\\n }\\n\\n for (let file of Object.keys(content)) {\\n if (node.content[file])\\n continue\\n const obj = content[file]\\n node.content[file] = obj\\n }\\n fs.refreshPathAttributes(node)\\n\\n // move files accordingly\\n for (let path of Object.entries(yarnball.metadata.paths)) {\\n const paths = fs.splitPath(path[1])\\n makeDir(paths[0])\\n const parent = fs.getNode(paths[0])\\n parent.content[paths[1]] = fs.getNode(\\\"/.tmp/mrrp/x/\\\" + path[0])\\n fs.refreshPathAttributes(parent)\\n }\\n\\n // keep track!\\n list[yarnball.metadata.name] = {\\n name: yarnball.metadata.name,\\n repo: reponame,\\n version: yarnball.metadata.version,\\n paths: [],\\n dependencies: yarnball.metadata.dependencies\\n }\\n\\n for (let path of Object.entries(yarnball.metadata.paths))\\n list[yarnball.metadata.name].paths.push(path[1])\\n\\n listNode.content = JSON.stringify(list)\\n\\n if (wanted && !world.includes[yarnball.metadata.name])\\n world.push(yarnball.metadata.name)\\n\\n if (interactive)\\n display.print(\\\"Package \\\" + yarnball.metadata.name + \\\" installed\\\", 0x6000)\\n\\n // handle dependencies but after install because we only keep one package in the cache hehe this is awful i'm sorry\\n for (let d of yarnball.metadata.dependencies) {\\n if (list[d])\\n continue\\n const reponame = await fetchPkg(d)\\n if (!reponame) {\\n display.print(\\\"Could not install dependency \\\" + d, 0x9000)\\n continue\\n }\\n const yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, interactive)\\n }\\n}\\n\\nasync function uninstall(package, interactive = true) {\\n const listNode = fs.getNode(\\\"/itty/packages.json\\\")\\n let list = JSON.parse(listNode.content)\\n\\n const pkginfo = list[package]\\n if (!pkginfo) {\\n if (interactive)\\n display.print(\\\"Package is not installed\\\", 0x6000)\\n return\\n }\\n \\n // ask the user!\\n if (interactive) {\\n display.print(\\\"Removing \\\" + pkginfo.name, 0x5000)\\n display.print(\\\"Warning: this will affect the following path(s):\\\", 0x2000)\\n for (let path of pkginfo.paths)\\n display.print(path, 0x2000)\\n \\n if (!await ask(\\\"Proceed?\\\"))\\n return\\n }\\n\\n // actually remove\\n for (let path of pkginfo.paths) {\\n const paths = fs.splitPath(path)\\n delete fs.getNode(paths[0]).content[paths[1]]\\n }\\n\\n delete list[pkginfo.name]\\n list = JSON.stringify(list)\\n listNode.content = list\\n\\n const i = world.indexOf(pkginfo.name)\\n if (i > -1)\\n world.splice(i)\\n\\n if (interactive)\\n display.print(\\\"Package removed\\\", 0x6000)\\n}\\n\\nasync function fetchPkg(package, repo, reponame, interactive = true) {\\n let repojson\\n let rlist = []\\n if (repo) {\\n repojson = repo\\n \\n if (!repojson) {\\n display.print(\\\"Cannot find repository info for \\\" + reponame, 0x2000)\\n io.error([1, \\\"Cannot find repository info\\\"])\\n }\\n } else {\\n // look for package in repos\\n for (let r of Object.entries(repoCache)) {\\n let rj = r[1]\\n \\n if (rj.packages[package])\\n rlist.push([r[0], r[1], rj])\\n }\\n \\n switch (rlist.length) {\\n case 0:\\n display.print(\\\"Cannot find package \\\" + package, 0x9000)\\n return false\\n case 1:\\n repojson = rlist[0][2]\\n repo = rlist[0][1]\\n reponame = rlist[0][0]\\n break\\n case 2:\\n display.print(\\\"Package \\\" + package + \\\" is available in the following repositories:\\\", 0x5000)\\n for (let i=0; i < rlist.length; i++) {\\n const v = rlist[i][2].packages[package].version\\n display.buffer(\\\"[\\\" + (i + 1) + \\\"] \\\")\\n display.buffer(rlist[i][0], 0x2000)\\n display.print(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\"), 0x4000)\\n }\\n const sel = await io.read([[\\\"Selection: \\\"]])\\n if (!sel)\\n return false\\n else {\\n repojson = rlist[sel-1][2]\\n repo = rlist[sel-1][1]\\n reponame = rlist[sel-1][0]\\n }\\n }\\n }\\n\\n // download\\n\\n let pkg\\n try {\\n pkg = await fetch(repojson.packages[package].url.replace(/^~/, repo.url))\\n pkg = await pkg.json()\\n } catch {\\n display.print(\\\"Cannot fetch package \\\" + package + \\\" from repository \\\" + reponame, 0x9000)\\n throw [2, \\\"Cannot fetch package\\\"]\\n }\\n\\n fs.removeNode(\\\"/.tmp/mrrp/dl\\\")\\n fs.makeDir(\\\"/.tmp/mrrp/dl\\\")\\n const dl = fs.getNode(\\\"/.tmp/mrrp/dl\\\")\\n dl.content.yarn = pkg\\n fs.refreshPathAttributes(dl)\\n\\n return reponame\\n}\\n\\nfunction want(package) {\\n const index = unwantedPkgs.indexOf(package)\\n if (index > -1)\\n unwantedPkgs.splice(index)\\n\\n if (pkgList[pkg])\\n for (let dep of pkgList[package].dependencies)\\n want(dep)\\n}\\n\\nswitch (args[0]) {\\n case \\\"yarn\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n try {\\n yarnball = fs.getNode(args[1])\\n } catch {\\n io.error([1, \\\"Cannot find yarnball\\\"])\\n }\\n\\n await install(yarnball, \\\"local yarnball\\\", true, true)\\n break\\n case \\\"uninstall\\\":\\n case \\\"remove\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n await uninstall(args[1])\\n break\\n case \\\"list-repos\\\":\\n for (let repo of Object.entries(repoList)) {\\n display.write(repo[0] + \\\" \\\", 0x2000)\\n display.print(repo[1].url)\\n }\\n break\\n case \\\"remove-repo\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n delete repoList[args[1]]\\n repoNode.content = JSON.stringify(repoList)\\n display.print(\\\"Removed repo \\\" + args[1], 0x6000)\\n await refreshCache()\\n break\\n case \\\"add-repo\\\":\\n if (args.length < 3) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n \\n args[2] = args[2].replace(/([^\\\\/])$/, \\\"$1/\\\")\\n\\n // fetch repo\\n try {\\n repo = await fetch(args[2] + \\\"repo.json\\\")\\n } catch {\\n display.print(\\\"Cannot fetch repository info\\\", 0x9000)\\n quit()\\n }\\n\\n if (repoList[args[1]]) {\\n display.print(\\\"Repository \\\" + args[1] + \\\" already exists.\\\", 0x2000)\\n if (!await ask(\\\"Overwrite?\\\"))\\n quit()\\n }\\n\\n repoList[args[1]] = {\\n url: args[2]\\n }\\n\\n repoNode.content = JSON.stringify(repoList)\\n display.print(\\\"Added repo \\\" + args[1] + \\\" with url \\\" + args[2], 0x6000)\\n await refreshCache()\\n break\\n case \\\"install\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n const reponame = await fetchPkg(args[1])\\n if (!reponame)\\n quit()\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, true, true)\\n break\\n case \\\"refresh-repos\\\":\\n await refreshCache()\\n display.print(\\\"Refreshed repository cache\\\", 0x6000)\\n break\\n case \\\"update\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n\\n for (let pkg of Object.entries(pkgList)) {\\n if (pkg[1].repo === \\\"local yarnball\\\" || !repoCache[pkg[1].repo])\\n continue\\n\\n const iv = pkg[1].version\\n const rv = repoCache[pkg[1].repo].packages[pkg[0]].version\\n if (rv[0] > iv[0] || rv[0] == iv[0] && rv[1] > iv[1] || rv[0] == iv[0] && rv[1] == iv[1] && rv[2] > iv[2])\\n updateList.push([pkg[0], pkg[1].repo, repoCache[pkg[1].repo]])\\n }\\n\\n if (!updateList.length) {\\n display.print(\\\"No packages need updating\\\", 0x3000)\\n quit()\\n }\\n\\n if (args[1] !== \\\"bg\\\") {\\n display.print(\\\"Packages to update:\\\", 0x6000)\\n for (let pkg of updateList)\\n display.print(pkg[0], 0x2000)\\n if (!await ask(\\\"Proceed?\\\"))\\n quit()\\n }\\n\\n for (let pkg of updateList) {\\n let f\\n try {\\n f = await fetchPkg(pkg[0], pkg[2], pkg[1], false)\\n } catch {\\n if (args[1] !== \\\"bg\\\")\\n display.print(\\\"Could not fetch \\\" + pkg[0] + \\\" from \\\" + pkg[1], 0x1000)\\n continue\\n }\\n if (f) {\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, pkg[1], false)\\n }\\n }\\n\\n if (args[1] !== \\\"bg\\\")\\n display.print(\\\"Updated packages\\\", 0x3000)\\n break\\n case \\\"list\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n\\n for (let pkg of Object.entries(pkgList)) {\\n display.buffer(pkg[0], 0x6000)\\n const v = pkg[1].version\\n display.buffer(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" \\\", 0x4000)\\n display.buffer(\\\"(\\\")\\n display.buffer(pkg[1].repo, 0x2000)\\n display.print(\\\")\\\")\\n }\\n break\\n case \\\"query\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n \\n for (let repo of Object.entries(repoCache)) {\\n for (let pkg of Object.entries(repo[1].packages)) {\\n if (pkg[0].match(args[1])) {\\n display.buffer(\\\"[\\\")\\n display.buffer(repo[0], 0x2000)\\n display.buffer(\\\"] \\\")\\n display.buffer(pkg[0], 0x6000)\\n const v = pkg[1].version\\n display.buffer(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\"), 0x4000)\\n if (pkgList[pkg[0]] && pkgList[pkg[0]].repo == repo[0]) {\\n display.buffer(\\\" (\\\")\\n const v = pkgList[pkg[0]].version\\n if (pkg[1].version[0] != v[0] || pkg[1].version[1] != v[1] || pkg[1].version[2] != v[2])\\n display.buffer(\\\"v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" \\\", 0x5000)\\n display.buffer(\\\"installed\\\", 0x5000)\\n display.buffer(\\\")\\\")\\n }\\n display.write(\\\"%n\\\")\\n }\\n }\\n }\\n break\\n case \\\"prune\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n unwantedPkgs = Object.keys(pkgList)\\n\\n for (let pkg of world)\\n want(pkg)\\n\\n if (unwantedPkgs.length) {\\n display.print(\\\"The following packages will be removed:\\\", 0x6000)\\n for (let pkg of unwantedPkgs)\\n display.print(pkg, 0x2000)\\n\\n if (await ask(\\\"Proceed?\\\"))\\n for (let pkg of unwantedPkgs)\\n uninstall(pkg, false)\\n } else\\n display.print(\\\"No unwanted packages to remove\\\", 0x3000)\\n break\\n case \\\"batch\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n const batchList = io.flines(fs.getNode(args[1])).filter(Boolean)\\n if (!batchList) {\\n display.print(\\\"Cannot find file\\\", 0x9000)\\n quit()\\n }\\n for (let pkg of batchList) {\\n const reponame = await fetchPkg(pkg)\\n if (!reponame)\\n quit()\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, true, true)\\n }\\n}\\n\\nconst worldfile = io.open(\\\"/itty/world\\\", \\\"w\\\")\\nfor (let w of world)\\n worldfile.print(w)\\nworldfile.writeOut()\\n\\nquit()\\n\\n// fs functions but copies that don't care about protectedness\\nfunction makeNode(path, mode) {\\n path = fs.resolve(path)\\n\\n // mode is bad?\\n if (mode != \\\"d\\\" && mode != \\\"f\\\")\\n throw [2, \\\"Invalid mode\\\"]\\n\\n // skip if it exists\\n const node = fs.getNode(path)\\n if (node && node.mode === \\\"d\\\")\\n return\\n else if (node)\\n throw [1, \\\"Node already exists\\\"]\\n\\n const paths = fs.splitPath(path)\\n const parentNode = fs.getNode(paths[0])\\n const pathEnd = paths[1]\\n\\n if (!parentNode)\\n throw [10, \\\"Parent node does not exist\\\"]\\n\\n // make the node\\n parentNode.content[pathEnd] = {\\n mode: mode,\\n protected: parentNode.protected ? true : false,\\n content: mode === \\\"d\\\" ? {} : \\\"\\\",\\n }\\n fs.setPathAttributes(parentNode.content[pathEnd], parentNode, pathEnd)\\n}\\n\\nfunction makeDir(path) {\\n path = fs.resolve(path)\\n const pathArray = path.split(\\\"/\\\").filter(Boolean)\\n let currentPath = \\\"\\\"\\n for (let part of pathArray) {\\n currentPath += \\\"/\\\" + part\\n makeNode(currentPath, \\\"d\\\")\\n }\\n}\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"mrrp","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"mrrp.js":"%B/mrrp.js"}},"content":"{\"mrrp.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"let yarnball\\nlet repoNode = fs.getNode(\\\"/itty/repos.json\\\")\\nlet repoList = JSON.parse(repoNode.content)\\nlet pkgList\\nlet updateList = []\\nlet world = io.flines(fs.getNode(\\\"/itty/world\\\")).filter(Boolean)\\nlet unwantedPkgs\\n\\n// we use some env vars, parse them\\nconst dirs = {\\n bin: fs.resolve(itty.env.dir_bin).slice(0, -1) || \\\"/itty/bin\\\",\\n docs: fs.resolve(itty.env.dir_docs).slice(0, -1) || \\\"/itty/docs\\\",\\n conf: fs.resolve(itty.env.dir_conf) + \\\"examples\\\" || \\\"/conf/examples\\\"\\n}\\n\\n// cache repo indexes, so querying and updating is faster\\nlet repoCache = fs.getNode(\\\"/.tmp/mrrp/repocache\\\")\\nif (!repoCache) {\\n fs.makeDir(\\\"/.tmp/mrrp/\\\")\\n fs.makeNode(\\\"/.tmp/mrrp/repocache\\\", \\\"f\\\")\\n await refreshCache()\\n} else {\\n repoCache = JSON.parse(repoCache.content) \\n}\\n\\n// refresh the repo cache!\\nasync function refreshCache() {\\n repoCache = fs.getNode(\\\"/.tmp/mrrp/repocache\\\")\\n const list = {}\\n for (let r of Object.entries(repoList)) {\\n let rj\\n try {\\n rj = await fetch(r[1].url + \\\"repo.json\\\")\\n rj = await rj.json()\\n } catch {\\n display.print(\\\"Cannot fetch repository info for \\\" + r[0], 0x9000)\\n continue\\n }\\n rj.url = r[1].url\\n list[r[0]] = rj\\n }\\n repoCache.content = JSON.stringify(list)\\n repoCache = list\\n}\\n\\n// confirmation as to whether to do things\\nasync function ask(message) {\\n const res = await io.read([[message + \\\" [y/N]: \\\"]])\\n\\n if (res.toLowerCase() !== \\\"y\\\" && res.toLowerCase() !== \\\"yes\\\") {\\n display.print(\\\"Aborting...\\\", 0x9000)\\n return false\\n }\\n\\n display.print(\\\"Proceeding...\\\", 0x3000)\\n return true\\n}\\n\\n// install a program\\nasync function install(yarnball, reponame, interactive = true, wanted) {\\n wanted = wanted || world.includes(yarnball.metadata.name)\\n\\n const listNode = fs.getNode(\\\"/itty/packages.json\\\")\\n let list = JSON.parse(listNode.content)\\n\\n // substitute %B, %C and %D in paths with env vars\\n for (let path of Object.keys(yarnball.metadata.paths)) {\\n let p = yarnball.metadata.paths[path]\\n p = p.replaceAll(\\\"%B\\\", dirs.bin)\\n p = p.replaceAll(\\\"%D\\\", dirs.docs)\\n p = p.replaceAll(\\\"%C\\\", dirs.conf)\\n yarnball.metadata.paths[path] = p\\n }\\n\\n // ask the user!\\n if (interactive) {\\n const v = yarnball.metadata.version\\n display.print(\\\"Installing \\\" + yarnball.metadata.name + \\\" version \\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" from \\\" + reponame, 0x5000)\\n display.print(\\\"Warning: this will affect the following path(s):\\\", 0x2000)\\n for (let path in yarnball.metadata.paths) {\\n display.print(yarnball.metadata.paths[path], 0x2000)\\n }\\n if (yarnball.metadata.dependencies.length)\\n display.print(\\\"The following dependencies also need to be installed:\\\", 0x6000)\\n for (let d of yarnball.metadata.dependencies) {\\n if (!list[d])\\n display.print(d, 0x6000)\\n }\\n if (!await ask(\\\"Proceed?\\\"))\\n return\\n }\\n\\n // uninstall if already installed\\n if (list[yarnball.metadata.name])\\n await uninstall(yarnball.metadata.name, false)\\n\\n // unspool the yarnball\\n fs.removeNode(\\\"/.tmp/mrrp/x\\\")\\n fs.makeDir(\\\"/.tmp/mrrp/x\\\")\\n const node = fs.getNode(\\\"/.tmp/mrrp/x\\\")\\n let content\\n\\n try {\\n content = JSON.parse(yarnball.content)\\n } catch {\\n io.error([5, \\\"Cannot parse yarnball\\\"])\\n }\\n\\n for (let file of Object.keys(content)) {\\n if (node.content[file])\\n continue\\n const obj = content[file]\\n node.content[file] = obj\\n }\\n fs.refreshPathAttributes(node)\\n\\n // move files accordingly\\n for (let path of Object.entries(yarnball.metadata.paths)) {\\n const paths = fs.splitPath(path[1])\\n makeDir(paths[0])\\n const parent = fs.getNode(paths[0])\\n parent.content[paths[1]] = fs.getNode(\\\"/.tmp/mrrp/x/\\\" + path[0])\\n fs.refreshPathAttributes(parent)\\n }\\n\\n // keep track!\\n list[yarnball.metadata.name] = {\\n name: yarnball.metadata.name,\\n repo: reponame,\\n version: yarnball.metadata.version,\\n paths: [],\\n dependencies: yarnball.metadata.dependencies\\n }\\n\\n for (let path of Object.entries(yarnball.metadata.paths))\\n list[yarnball.metadata.name].paths.push(path[1])\\n\\n listNode.content = JSON.stringify(list)\\n\\n if (wanted && !world.includes[yarnball.metadata.name])\\n world.push(yarnball.metadata.name)\\n\\n if (interactive)\\n display.print(\\\"Package \\\" + yarnball.metadata.name + \\\" installed\\\", 0x6000)\\n\\n // handle dependencies but after install because we only keep one package in the cache hehe this is awful i'm sorry\\n for (let d of yarnball.metadata.dependencies) {\\n if (list[d])\\n continue\\n const reponame = await fetchPkg(d)\\n if (!reponame) {\\n display.print(\\\"Could not install dependency \\\" + d, 0x9000)\\n continue\\n }\\n const yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, interactive)\\n }\\n}\\n\\nasync function uninstall(package, interactive = true) {\\n const listNode = fs.getNode(\\\"/itty/packages.json\\\")\\n let list = JSON.parse(listNode.content)\\n\\n const pkginfo = list[package]\\n if (!pkginfo) {\\n if (interactive)\\n display.print(\\\"Package is not installed\\\", 0x6000)\\n return\\n }\\n \\n // ask the user!\\n if (interactive) {\\n display.print(\\\"Removing \\\" + pkginfo.name, 0x5000)\\n display.print(\\\"Warning: this will affect the following path(s):\\\", 0x2000)\\n for (let path of pkginfo.paths)\\n display.print(path, 0x2000)\\n \\n if (!await ask(\\\"Proceed?\\\"))\\n return\\n }\\n\\n // actually remove\\n for (let path of pkginfo.paths) {\\n const paths = fs.splitPath(path)\\n delete fs.getNode(paths[0]).content[paths[1]]\\n }\\n\\n delete list[pkginfo.name]\\n list = JSON.stringify(list)\\n listNode.content = list\\n\\n const i = world.indexOf(pkginfo.name)\\n if (i > -1)\\n world.splice(i)\\n\\n if (interactive)\\n display.print(\\\"Package removed\\\", 0x6000)\\n}\\n\\nasync function fetchPkg(package, repo, reponame, interactive = true) {\\n let repojson\\n let rlist = []\\n if (repo) {\\n repojson = repo\\n \\n if (!repojson) {\\n display.print(\\\"Cannot find repository info for \\\" + reponame, 0x2000)\\n io.error([1, \\\"Cannot find repository info\\\"])\\n }\\n } else {\\n // look for package in repos\\n for (let r of Object.entries(repoCache)) {\\n let rj = r[1]\\n \\n if (rj.packages[package])\\n rlist.push([r[0], r[1], rj])\\n }\\n \\n switch (rlist.length) {\\n case 0:\\n display.print(\\\"Cannot find package \\\" + package, 0x9000)\\n return false\\n case 1:\\n repojson = rlist[0][2]\\n repo = rlist[0][1]\\n reponame = rlist[0][0]\\n break\\n case 2:\\n display.print(\\\"Package \\\" + package + \\\" is available in the following repositories:\\\", 0x5000)\\n for (let i=0; i < rlist.length; i++) {\\n const v = rlist[i][2].packages[package].version\\n display.buffer(\\\"[\\\" + (i + 1) + \\\"] \\\")\\n display.buffer(rlist[i][0], 0x2000)\\n display.print(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\"), 0x4000)\\n }\\n const sel = await io.read([[\\\"Selection: \\\"]])\\n if (!sel)\\n return false\\n else {\\n repojson = rlist[sel-1][2]\\n repo = rlist[sel-1][1]\\n reponame = rlist[sel-1][0]\\n }\\n }\\n }\\n\\n // download\\n\\n let pkg\\n try {\\n pkg = await fetch(repojson.packages[package].url.replace(/^~/, repo.url))\\n pkg = await pkg.json()\\n } catch {\\n display.print(\\\"Cannot fetch package \\\" + package + \\\" from repository \\\" + reponame, 0x9000)\\n throw [2, \\\"Cannot fetch package\\\"]\\n }\\n\\n fs.removeNode(\\\"/.tmp/mrrp/dl\\\")\\n fs.makeDir(\\\"/.tmp/mrrp/dl\\\")\\n const dl = fs.getNode(\\\"/.tmp/mrrp/dl\\\")\\n dl.content.yarn = pkg\\n fs.refreshPathAttributes(dl)\\n\\n return reponame\\n}\\n\\nfunction want(package) {\\n const index = unwantedPkgs.indexOf(package)\\n if (index > -1)\\n unwantedPkgs.splice(index)\\n\\n if (pkgList[pkg])\\n for (let dep of pkgList[package].dependencies)\\n want(dep)\\n}\\n\\nswitch (args[0]) {\\n case \\\"yarn\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n try {\\n yarnball = fs.getNode(args[1])\\n } catch {\\n io.error([1, \\\"Cannot find yarnball\\\"])\\n }\\n\\n await install(yarnball, \\\"local yarnball\\\", true, true)\\n break\\n case \\\"uninstall\\\":\\n case \\\"remove\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n await uninstall(args[1])\\n break\\n case \\\"list-repos\\\":\\n for (let repo of Object.entries(repoList)) {\\n display.write(repo[0] + \\\" \\\", 0x2000)\\n display.print(repo[1].url)\\n }\\n break\\n case \\\"remove-repo\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n delete repoList[args[1]]\\n repoNode.content = JSON.stringify(repoList)\\n display.print(\\\"Removed repo \\\" + args[1], 0x6000)\\n await refreshCache()\\n break\\n case \\\"add-repo\\\":\\n if (args.length < 3) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n \\n args[2] = args[2].replace(/([^\\\\/])$/, \\\"$1/\\\")\\n\\n // fetch repo\\n try {\\n repo = await fetch(args[2] + \\\"repo.json\\\")\\n } catch {\\n display.print(\\\"Cannot fetch repository info\\\", 0x9000)\\n quit()\\n }\\n\\n if (repoList[args[1]]) {\\n display.print(\\\"Repository \\\" + args[1] + \\\" already exists.\\\", 0x2000)\\n if (!await ask(\\\"Overwrite?\\\"))\\n quit()\\n }\\n\\n repoList[args[1]] = {\\n url: args[2]\\n }\\n\\n repoNode.content = JSON.stringify(repoList)\\n display.print(\\\"Added repo \\\" + args[1] + \\\" with url \\\" + args[2], 0x6000)\\n await refreshCache()\\n break\\n case \\\"install\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n const reponame = await fetchPkg(args[1])\\n if (!reponame)\\n quit()\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, true, true)\\n break\\n case \\\"refresh-repos\\\":\\n await refreshCache()\\n display.print(\\\"Refreshed repository cache\\\", 0x6000)\\n break\\n case \\\"update\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n\\n for (let pkg of Object.entries(pkgList)) {\\n if (pkg[1].repo === \\\"local yarnball\\\" || !repoCache[pkg[1].repo])\\n continue\\n\\n const iv = pkg[1].version\\n const rv = repoCache[pkg[1].repo].packages[pkg[0]].version\\n if (rv[0] > iv[0] || rv[0] == iv[0] && rv[1] > iv[1] || rv[0] == iv[0] && rv[1] == iv[1] && rv[2] > iv[2])\\n updateList.push([pkg[0], pkg[1].repo, repoCache[pkg[1].repo]])\\n }\\n\\n if (!updateList.length) {\\n display.print(\\\"No packages need updating\\\", 0x3000)\\n quit()\\n }\\n\\n if (args[1] !== \\\"bg\\\") {\\n display.print(\\\"Packages to update:\\\", 0x6000)\\n for (let pkg of updateList)\\n display.print(pkg[0], 0x2000)\\n if (!await ask(\\\"Proceed?\\\"))\\n quit()\\n }\\n\\n for (let pkg of updateList) {\\n let f\\n try {\\n f = await fetchPkg(pkg[0], pkg[2], pkg[1], false)\\n } catch {\\n if (args[1] !== \\\"bg\\\")\\n display.print(\\\"Could not fetch \\\" + pkg[0] + \\\" from \\\" + pkg[1], 0x1000)\\n continue\\n }\\n if (f) {\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, pkg[1], false)\\n }\\n }\\n\\n if (args[1] !== \\\"bg\\\")\\n display.print(\\\"Updated packages\\\", 0x3000)\\n break\\n case \\\"list\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n\\n for (let pkg of Object.entries(pkgList)) {\\n display.buffer(pkg[0], 0x6000)\\n const v = pkg[1].version\\n display.buffer(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" \\\", 0x4000)\\n display.buffer(\\\"(\\\")\\n display.buffer(pkg[1].repo, 0x2000)\\n display.print(\\\")\\\")\\n }\\n break\\n case \\\"query\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n \\n for (let repo of Object.entries(repoCache)) {\\n for (let pkg of Object.entries(repo[1].packages)) {\\n if (pkg[0].match(args[1])) {\\n display.buffer(\\\"[\\\")\\n display.buffer(repo[0], 0x2000)\\n display.buffer(\\\"] \\\")\\n display.buffer(pkg[0], 0x6000)\\n const v = pkg[1].version\\n display.buffer(\\\" v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\"), 0x4000)\\n if (pkgList[pkg[0]] && pkgList[pkg[0]].repo == repo[0]) {\\n display.buffer(\\\" (\\\")\\n const v = pkgList[pkg[0]].version\\n if (pkg[1].version[0] != v[0] || pkg[1].version[1] != v[1] || pkg[1].version[2] != v[2])\\n display.buffer(\\\"v\\\" + v[0] + (v[1] ? \\\".\\\" + v[1] : \\\".0\\\") + (v[2] ? \\\".\\\" + v[2] : \\\"\\\") + \\\" \\\", 0x5000)\\n display.buffer(\\\"installed\\\", 0x5000)\\n display.buffer(\\\")\\\")\\n }\\n display.write(\\\"%n\\\")\\n }\\n }\\n }\\n break\\n case \\\"prune\\\":\\n try {\\n pkgList = JSON.parse(fs.getNode(\\\"/itty/packages.json\\\").content)\\n } catch {\\n display.print(\\\"Cannot parse package list\\\", 0x9000)\\n quit() \\n }\\n unwantedPkgs = Object.keys(pkgList)\\n\\n for (let pkg of world)\\n want(pkg)\\n\\n if (unwantedPkgs.length) {\\n display.print(\\\"The following packages will be removed:\\\", 0x6000)\\n for (let pkg of unwantedPkgs)\\n display.print(pkg, 0x2000)\\n\\n if (await ask(\\\"Proceed?\\\"))\\n for (let pkg of unwantedPkgs)\\n uninstall(pkg, false)\\n } else\\n display.print(\\\"No unwanted packages to remove\\\", 0x3000)\\n break\\n case \\\"batch\\\":\\n if (args.length < 2) {\\n display.print(\\\"Not enough arguments\\\", 0x1000)\\n quit()\\n }\\n const batchList = io.flines(fs.getNode(args[1])).filter(Boolean)\\n if (!batchList) {\\n display.print(\\\"Cannot find file\\\", 0x9000)\\n quit()\\n }\\n for (let pkg of batchList) {\\n const reponame = await fetchPkg(pkg)\\n if (!reponame)\\n quit()\\n yarnball = fs.getNode(\\\"/.tmp/mrrp/dl/yarn\\\")\\n await install(yarnball, reponame, true, true)\\n }\\n}\\n\\nconst worldfile = io.open(\\\"/itty/world\\\", \\\"w\\\")\\nfor (let w of world)\\n worldfile.print(w)\\nworldfile.writeOut()\\n\\nquit()\\n\\n// fs functions but copies that don't care about protectedness\\nfunction makeNode(path, mode) {\\n path = fs.resolve(path)\\n\\n // mode is bad?\\n if (mode != \\\"d\\\" && mode != \\\"f\\\")\\n throw [2, \\\"Invalid mode\\\"]\\n\\n // skip if it exists\\n const node = fs.getNode(path)\\n if (node && node.mode === \\\"d\\\")\\n return\\n else if (node)\\n throw [1, \\\"Node already exists\\\"]\\n\\n const paths = fs.splitPath(path)\\n const parentNode = fs.getNode(paths[0])\\n const pathEnd = paths[1]\\n\\n if (!parentNode)\\n throw [10, \\\"Parent node does not exist\\\"]\\n\\n // make the node\\n parentNode.content[pathEnd] = {\\n mode: mode,\\n protected: parentNode.protected ? true : false,\\n content: mode === \\\"d\\\" ? {} : \\\"\\\",\\n }\\n fs.setPathAttributes(parentNode.content[pathEnd], parentNode, pathEnd)\\n}\\n\\nfunction makeDir(path) {\\n path = fs.resolve(path)\\n const pathArray = path.split(\\\"/\\\").filter(Boolean)\\n let currentPath = \\\"\\\"\\n for (let part of pathArray) {\\n currentPath += \\\"/\\\" + part\\n makeNode(currentPath, \\\"d\\\")\\n }\\n}\"}}"} \ No newline at end of file diff --git a/mv.yarn b/mv.yarn index cb4d5fd..eadbccd 100644 --- a/mv.yarn +++ b/mv.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"mv","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"mv.js":"%B/mv.js"}},"content":"{\"mv.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[0] && !args[1]) {\\n display.print(\\\"Not enough arguments\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.moveNode(args[0], args[1])\\n} catch (e) {\\n display.print(e[1] || \\\"Error moving node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"mv","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"mv.js":"%B/mv.js"}},"content":"{\"mv.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[0] && !args[1]) {\\n display.print(\\\"Not enough arguments\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.moveNode(args[0], args[1])\\n} catch (e) {\\n display.print(e[1] || \\\"Error moving node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file diff --git a/programs.yarn b/programs.yarn index aab89d9..9c4642a 100644 --- a/programs.yarn +++ b/programs.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"programs","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"programs.js":"%B/programs.js"}},"content":"{\"programs.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"for (let path of itty.env.path) {\\n path = fs.listDir(path)\\n for (let p in path) {\\n p = path[p]\\n if (p.ext === \\\"js\\\") {\\n const name = p.name.slice(0, -3)\\n if (itty.cursorX + name.length >= itty.width) {\\n itty.cursorX = 0\\n itty.cursorY++\\n }\\n while (itty.cursorY >= itty.height)\\n display.lift()\\n display.buffer(name + \\\" \\\")\\n }\\n }\\n}\\n \\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"programs","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"programs.js":"%B/programs.js"}},"content":"{\"programs.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"for (let path of itty.env.path) {\\n path = fs.listDir(path)\\n for (let p in path) {\\n p = path[p]\\n if (p.ext === \\\"js\\\") {\\n const name = p.name.slice(0, -3)\\n if (itty.cursorX + name.length >= itty.width) {\\n itty.cursorX = 0\\n itty.cursorY++\\n }\\n while (itty.cursorY >= itty.height)\\n display.lift()\\n display.buffer(name + \\\" \\\")\\n }\\n }\\n}\\n \\ndisplay.render()\\nquit()\"}}"} \ No newline at end of file diff --git a/rm.yarn b/rm.yarn index acd130c..710fb35 100644 --- a/rm.yarn +++ b/rm.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"rm","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"rm.js":"%B/rm.js"}},"content":"{\"rm.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.removeNode(args[0])\\n} catch (e) {\\n display.print(e[1] || \\\"Error removing node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"rm","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"rm.js":"%B/rm.js"}},"content":"{\"rm.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.removeNode(args[0])\\n} catch (e) {\\n display.print(e[1] || \\\"Error removing node\\\", 0x9000)\\n}\\n\\nquit()\"}}"} \ No newline at end of file diff --git a/shutdown.yarn b/shutdown.yarn index 1ac0f97..7ecd0a2 100644 --- a/shutdown.yarn +++ b/shutdown.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"shutdown","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"shutdown.js":"%B/shutdown.js"}},"content":"{\"shutdown.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"exec.shutdown(); quit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"shutdown","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"shutdown.js":"%B/shutdown.js"}},"content":"{\"shutdown.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"exec.shutdown(); quit()\"}}"} \ No newline at end of file diff --git a/slog.yarn b/slog.yarn index 5d8b483..fbc6a78 100644 --- a/slog.yarn +++ b/slog.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"slog","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"slog.js":"%B/slog.js"}},"content":"{\"slog.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"// ensure log file exists\\n\\nlet logfile\\n\\ntry {\\n logfile = io.open(\\\"/itty/slog\\\", \\\"a\\\")\\n} catch {}\\n\\nif (!logfile) {\\n fs.getNode(\\\"/itty/\\\").content[\\\"slog\\\"] = {\\n protected: false,\\n mode: \\\"f\\\",\\n content: \\\"\\\",\\n parent: fs.getNode(\\\"/itty/\\\"),\\n name: \\\"slog\\\",\\n js: \\\"\\\",\\n metadata: {}\\n }\\n logfile = io.open(\\\"/itty/slog\\\", \\\"a\\\")\\n}\\n\\nconst message = JSON.parse(pipe)\\n\\nif (message[1][0] !== 0)\\n console.log(\\\"ERROR\\\", message[1])\\n\\nlogfile.print(`(${message[0].id}/${message[0].uid}) ${message[0].name}: [${message[1][0] || \\\"INFO\\\"}] ${message[1][1]}`)\\nlogfile.writeOut()\\n\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"slog","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"slog.js":"%B/slog.js"}},"content":"{\"slog.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"// ensure log file exists\\n\\nlet logfile\\n\\ntry {\\n logfile = io.open(\\\"/itty/slog\\\", \\\"a\\\")\\n} catch {}\\n\\nif (!logfile) {\\n fs.getNode(\\\"/itty/\\\").content[\\\"slog\\\"] = {\\n protected: false,\\n mode: \\\"f\\\",\\n content: \\\"\\\",\\n parent: fs.getNode(\\\"/itty/\\\"),\\n name: \\\"slog\\\",\\n js: \\\"\\\",\\n metadata: {}\\n }\\n logfile = io.open(\\\"/itty/slog\\\", \\\"a\\\")\\n}\\n\\nconst message = JSON.parse(pipe)\\n\\nif (message[1][0] !== 0)\\n console.log(\\\"ERROR\\\", message[1])\\n\\nlogfile.print(`(${message[0].id}/${message[0].uid}) ${message[0].name}: [${message[1][0] || \\\"INFO\\\"}] ${message[1][1]}`)\\nlogfile.writeOut()\\n\\nquit()\"}}"} \ No newline at end of file diff --git a/touch.yarn b/touch.yarn index 56f0275..ecce0b2 100644 --- a/touch.yarn +++ b/touch.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"touch","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"touch.js":"%B/touch.js"}},"content":"{\"touch.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.makeNode(args[0], \\\"f\\\")\\n} catch (e) {\\n switch (e[0]) {\\n case 1:\\n display.print(\\\"File already exists\\\", 0xf000)\\n break\\n case 3:\\n display.print(\\\"Parent directory is protected\\\", 0x9000)\\n break\\n case 10:\\n display.print(\\\"Parent directory does not exist\\\", 0x9000)\\n break\\n default:\\n display.print(\\\"Error creating file\\\", 0x9000)\\n }\\n}\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"touch","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"touch.js":"%B/touch.js"}},"content":"{\"touch.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"if (!args[0]) {\\n display.print(\\\"No path provided\\\", 0xf000)\\n quit()\\n}\\n\\ntry {\\n fs.makeNode(args[0], \\\"f\\\")\\n} catch (e) {\\n switch (e[0]) {\\n case 1:\\n display.print(\\\"File already exists\\\", 0xf000)\\n break\\n case 3:\\n display.print(\\\"Parent directory is protected\\\", 0x9000)\\n break\\n case 10:\\n display.print(\\\"Parent directory does not exist\\\", 0x9000)\\n break\\n default:\\n display.print(\\\"Error creating file\\\", 0x9000)\\n }\\n}\\nquit()\"}}"} \ No newline at end of file diff --git a/yarn.yarn b/yarn.yarn index 1f2162d..006b2d8 100644 --- a/yarn.yarn +++ b/yarn.yarn @@ -1 +1 @@ -{"protected":false,"mode":"f","metadata":{"name":"yarn","author":"Luna Magdalena :3","version":[1],"dependencies":[],"runner":[],"paths":{"yarn.js":"%B/yarn.js"}},"content":"{\"yarn.js\":{\"protected\":true,\"metadata\":{},\"mode\":\"f\",\"content\":\"function spool(nodes) {\\n const yarnball = {}\\n\\n for (let node of nodes) {\\n let n\\n try {\\n n = fs.getNode(node)\\n } catch {\\n continue\\n }\\n\\n yarnball[n.name] = n\\n }\\n\\n return JSON.stringify(yarnball, (key, value) => {if (key === \\\"parent\\\" || key === \\\"name\\\" || key === \\\"ext\\\") {return undefined}; return value})\\n}\\n\\nfunction unspool(yarnball, path) {\\n fs.makeDir(path)\\n const node = fs.getNode(path)\\n if (node.protected)\\n io.error([3, \\\"Destination is protected\\\"])\\n\\n try {\\n yarnball = JSON.parse(yarnball)\\n } catch {\\n io.error([5, \\\"Cannot parse yarnball\\\"])\\n }\\n\\n for (let file of Object.keys(yarnball)) {\\n if (node.content[file])\\n continue\\n const obj = yarnball[file]\\n node.content[file] = obj\\n }\\n fs.refreshPathAttributes(node)\\n}\\n\\nlet yarnfile\\nlet meta\\nlet jsonfile\\n\\nswitch (args[0]) {\\n case \\\"spool\\\":\\n yarnfile = io.open(args[1], \\\"w\\\")\\n yarnfile.write(spool(args.slice(2)))\\n yarnfile.writeOut()\\n break\\n case \\\"unspool\\\":\\n yarnfile = io.open(args[1], \\\"r\\\")\\n unspool(yarnfile.read(), args[2])\\n break\\n case \\\"get-metadata\\\":\\n yarnfile = io.open(args[1], \\\"r\\\")\\n if (args[2])\\n display.print(JSON.stringify(fs.getMetadata(yarnfile, args[2])))\\n else\\n for (let m of Object.keys(yarnfile.metadata))\\n display.print(m + \\\": \\\" + JSON.stringify(fs.getMetadata(yarnfile, m)))\\n break\\n case \\\"set-metadata\\\":\\n yarnfile = fs.getNode(args[1])\\n meta = await io.read()\\n fs.setMetadata(yarnfile, args[2], meta)\\n break\\n case \\\"metadata-from-json\\\":\\n try {\\n yarnfile = fs.getNode(args[1])\\n } catch {\\n io.error([1, \\\"Cannot find yarnball\\\"])\\n }\\n if (yarnfile.protected)\\n io.error([2, \\\"Yarnball is protected\\\"])\\n\\n try {\\n jsonfile = fs.getNode(args[2])\\n } catch {\\n io.error([1, \\\"Cannot find JSON file\\\"])\\n }\\n\\n try {\\n meta = JSON.parse(jsonfile.content)\\n } catch {\\n io.error([6, \\\"Cannot parse JSON\\\"])\\n }\\n\\n yarnfile.metadata = meta\\n break\\n}\\nquit()\"}}"} \ No newline at end of file +{"protected":false,"mode":"f","metadata":{"name":"yarn","author":"Luna Magdalena :3","version":[1],"dependencies":[],"paths":{"yarn.js":"%B/yarn.js"}},"content":"{\"yarn.js\":{\"protected\":true,\"metadata\":{\"runner\":[]},\"mode\":\"f\",\"content\":\"function spool(nodes) {\\n const yarnball = {}\\n\\n for (let node of nodes) {\\n let n\\n try {\\n n = fs.getNode(node)\\n } catch {\\n continue\\n }\\n\\n yarnball[n.name] = n\\n }\\n\\n return JSON.stringify(yarnball, (key, value) => {if (key === \\\"parent\\\" || key === \\\"name\\\" || key === \\\"ext\\\") {return undefined}; return value})\\n}\\n\\nfunction unspool(yarnball, path) {\\n fs.makeDir(path)\\n const node = fs.getNode(path)\\n if (node.protected)\\n io.error([3, \\\"Destination is protected\\\"])\\n\\n try {\\n yarnball = JSON.parse(yarnball)\\n } catch {\\n io.error([5, \\\"Cannot parse yarnball\\\"])\\n }\\n\\n for (let file of Object.keys(yarnball)) {\\n if (node.content[file])\\n continue\\n const obj = yarnball[file]\\n node.content[file] = obj\\n }\\n fs.refreshPathAttributes(node)\\n}\\n\\nlet yarnfile\\nlet meta\\nlet jsonfile\\n\\nswitch (args[0]) {\\n case \\\"spool\\\":\\n yarnfile = io.open(args[1], \\\"w\\\")\\n yarnfile.write(spool(args.slice(2)))\\n yarnfile.writeOut()\\n break\\n case \\\"unspool\\\":\\n yarnfile = io.open(args[1], \\\"r\\\")\\n unspool(yarnfile.read(), args[2])\\n break\\n case \\\"get-metadata\\\":\\n yarnfile = io.open(args[1], \\\"r\\\")\\n if (args[2])\\n display.print(JSON.stringify(fs.getMetadata(yarnfile, args[2])))\\n else\\n for (let m of Object.keys(yarnfile.metadata))\\n display.print(m + \\\": \\\" + JSON.stringify(fs.getMetadata(yarnfile, m)))\\n break\\n case \\\"set-metadata\\\":\\n yarnfile = fs.getNode(args[1])\\n meta = await io.read()\\n fs.setMetadata(yarnfile, args[2], meta)\\n break\\n case \\\"metadata-from-json\\\":\\n try {\\n yarnfile = fs.getNode(args[1])\\n } catch {\\n io.error([1, \\\"Cannot find yarnball\\\"])\\n }\\n if (yarnfile.protected)\\n io.error([2, \\\"Yarnball is protected\\\"])\\n\\n try {\\n jsonfile = fs.getNode(args[2])\\n } catch {\\n io.error([1, \\\"Cannot find JSON file\\\"])\\n }\\n\\n try {\\n meta = JSON.parse(jsonfile.content)\\n } catch {\\n io.error([6, \\\"Cannot parse JSON\\\"])\\n }\\n\\n yarnfile.metadata = meta\\n break\\n}\\nquit()\"}}"} \ No newline at end of file