diff --git a/src/components/konsole.vue b/src/components/konsole.vue index 31d7dc1..ab1a970 100644 --- a/src/components/konsole.vue +++ b/src/components/konsole.vue @@ -1,5 +1,5 @@ - - diff --git a/src/misc/konsole.js b/src/misc/konsole.js deleted file mode 100644 index 2f4e04b..0000000 --- a/src/misc/konsole.js +++ /dev/null @@ -1,344 +0,0 @@ -window.cli = { - // Element references - _input: null, - _parent: null, - _prompt: null, - _output: null, - - // CLI State - _history: [], - _index: 0, - pwd: '/', - hostname: 'virtual', - env: {}, - exec: {}, - filesystem: {}, - user: 'root', - version: '0.3.0', - - build: (elementId) => { - window.cli._parent = document.querySelector(elementId); - if(!window.cli._parent) - throw new Error(`Could not create konsole, element "${elementId}" does not exist`); - - window.cli._parent.innerHTML = ` -
-
-
- - -
-
`; - - window.cli._input = document.querySelector(elementId + ' .cli-stdin-input'); - window.cli._prompt = document.querySelector(elementId + ' .cli-stdin-prompt'); - window.cli._output = document.querySelector(elementId + ' .cli-stdout'); - window.cli._input.addEventListener('keyup', (e) => { - if(e.key == "Enter") { - window.cli.disable(); - if(!!window.cli._input.value) { - window.cli._history.push(window.cli._input.value); - window.cli._index = window.cli._history.length; - window.cli.stdIn(window.cli._input.value) - } - window.cli._input.value = ''; - window.cli.enable(); - } else if(e.key == 'Up' || e.key == 'ArrowUp') { - if(window.cli._index > 0) window.cli._index--; - window.cli._input.value = window.cli._index == window.cli._history.length ? '' : window.cli._history[window.cli._index]; - setTimeout(() => { - const end = window.cli._input.value.length; - window.cli._input.setSelectionRange(end, end); - window.cli._input.focus(); - }, 1) - } else if(e.key == 'Down' || e.key == 'ArrowDown') { - if(window.cli._index < window.cli._history.length) window.cli._index++; - window.cli._input.value = window.cli._index == window.cli._history.length ? '' : window.cli._history[window.cli._index]; - setTimeout(() => { - const end = window.cli._input.value.length; - window.cli._input.setSelectionRange(end, end); - window.cli._input.focus(); - }, 1) - } - }); - setTimeout(() => window.cli.exec['banner'].run(), 1); - }, - disable: () => { - window.cli._input.disabled = true; - window.cli._prompt.style.visibility = 'hidden'; - }, - enable: () => { - window.cli._input.disabled = false; - window.cli._input.focus(); - window.cli._prompt.style.visibility = 'visible'; - }, - - path: (path=window.cli.pwd) => { - let p = path[0] == '/'? path : (window.cli.pwd + (window.cli.pwd.endsWith('/') ? '' : '/') + path.replace('./', '')) - .replaceAll('//', '/'); - const parts = p.split('/').filter(p => !!p); - for(let i = 0; i < parts.length; i++) { - if(parts[i] == '..') { - i--; - parts.splice(i, 2); - i--; - } - } - return '/' + (parts.length ? parts.join('/') : ''); - }, - prompt: () => `${window.cli.user}@${window.cli.hostname}:${window.cli.pwd}${window.cli.user == 'root' ? '#' : '$'}`, - fs: (path, set) => { - return window.cli.path(path).split('/').filter(p => !!p).reduce((t, p, i, arr) => { - if(!t?.hasOwnProperty(p)) { - if(set == undefined) return undefined; - t[p] = {}; - } - if(set !== undefined && i == arr.length - 1) { - if(set == null) delete t[p]; - else t[p] = set; - } - return t[p]; - }, window.cli.filesystem); - }, - stdErr: (text) => { - const p = document.createElement('p'); - p.classList.add('cli-stdout-line'); - p.classList.add('cli-stdout-error'); - p.innerText = text; - window.cli._output.appendChild(p); - }, - stdIn:(command, silent=false) => { - (Array.isArray(command) ? command.join(' ') : command).split(';').filter(c => !!c).forEach(c => { - const parts = c.match(/(?:[^\s"]+|"[^"]*")+/g); - if(!parts) return; - - const exec = window.cli.exec[parts[0]]; - if(!exec?.run) { - window.cli.stdErr(`${window.cli.prompt()} ${command}\n${parts[0]}: command not found`); - } else { - try { - const args = parts.slice(1).map(a => (a[0] == '"' || a[0] == "'") ? a.slice(1, -1) : a); - const out = exec.run(args); - if(!silent) window.cli.stdOut(`${window.cli.prompt()} ${command}${out ? '\n' + out : ''}`); - } catch(err) { - console.error(err); - window.cli.stdErr(`${window.cli.prompt()} ${command}\n${err.message || `${parts[0]}: exited with a non-zero status`}`); - } - } - }); - }, - stdOut: (text, html=false) => { - const p = document.createElement('p'); - p.classList.add('cli-stdout-line'); - p[html ? 'innerHTML' : 'innerText'] = text; - window.cli._output.appendChild(p); - }, - type: (text, speed=150) => { - let counter = 0; - return new Promise(res => { - let typing = setInterval(() => { - if(counter < text.length) { - window.cli._input.value += text[counter]; - } else { - clearInterval(typing); - setTimeout(() => { - window.cli.stdIn(text); - window.cli._input.value = ''; - res(); - }, 750); - } - counter++; - }, speed); - }); - } -}; - -window.cli.exec['banner'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Display login banner'; - }, - run: args => { - window.cli.stdOut(`Konsole ${window.cli.version} LTS ${window.cli.hostname} tty1\n\n${window.cli.hostname} login: ${window.cli.user}\npassword:\n\n`); - } -} -window.cli.exec['cd'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Clear console output'; - }, - run: args => { - const path = window.cli.fs(args[0]); - if(!path) throw new Error(`cd: \'${args[0]}\': No such file or directory`) - - window.cli.pwd = window.cli.path(args[0]); - window.cli._prompt.innerText = window.cli.prompt(); - } -} -window.cli.exec['clear'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Clear console output'; - }, - run: args => { - setTimeout(() => window.cli._output.innerHTML = '', 1); - } -} -window.cli.exec['date'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Get current date & time'; - }, - run: args => { - return (new Date()).toLocaleString(); - } -} -window.cli.exec['echo'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Output text to console'; - }, - run: args => { - return args.join(' '); - } -} -window.cli.exec['exit'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'End session'; - }, - run: args => { - window.cli.stdIn('clear'); - window.cli._history = []; - window.cli._index = 0; - window.cli.stdIn('banner'); - } -} -window.cli.exec['help'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Display all commands'; - }, - run: args => { - return `Konsole v${window.cli.version} - A prototype bash emulator written by Zakary Timson\n\n` + - Object.keys(window.cli.exec).map(command => `${command} - ${window.cli.exec[command].help()}`).join('\n'); - } -} -window.cli.exec['hostname'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Get computer hostname'; - }, - run: args => { - return window.cli.hostname; - } -} -window.cli.exec['ls'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Display directory contents'; - }, - run: args => { - const target = window.cli.fs(args[0]); - if(!target) throw new Error(`ls: cannot access \'${args[0]}\': No such file or directory`) - return Object.keys(target).reduce((acc, p) => acc + `${p}\n`, ''); - } -} -window.cli.exec['man'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'View command\'s manual'; - }, - run: args => { - return window.cli.exec[args[0]].help(); - } -} -window.cli.exec['mkdir'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Create new directory'; - }, - run: args => { - if(!args[0]) throw new Error('mkdir: missing operand'); - window.cli.fs(args[0], {}); - } -} -window.cli.exec['pwd'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Get present working directory'; - }, - run: args => { - return window.cli.pwd; - } -} -window.cli.exec['rm'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Delete file or directory'; - }, - run: args => { - if(!args[0]) throw new Error('rm: missing operand'); - window.cli.fs(args[0], null); - } -} -window.cli.exec['shower-thought'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Random shower thought'; - }, - run: args => { - const motd = [ - 'Why do kamikaze pilots wear helmets?', - 'How are giraffes real, but unicorns made up', - 'When you are a kid you don\'t realize you are also watching your parents grow up', - 'Some one at Google was like "Yea, just have someone drive down every road on earth!"', - 'The number of people older than you never goes up', - 'When you brush your teeth you are cleaning your skeleton', - 'Pregnancy is like a group project where one person get\'s stuck with all the work', - 'If the universe wasn\'t infinite it would be even scarier', - 'Either we are alone in the universe or we are not. both are terrifying', - 'The object of golf is to play the least amount of golf.' - ]; - return motd[~~(Math.random() * motd.length)]; - } -} -window.cli.exec['whoami'] = { - autocomplete: () => { - return []; - }, - help: () => { - return 'Get current user account'; - }, - run: args => { - return window.cli.user; - } -} diff --git a/src/modules/konsole/commands/banner.js b/src/modules/konsole/commands/banner.js new file mode 100644 index 0000000..113976e --- /dev/null +++ b/src/modules/konsole/commands/banner.js @@ -0,0 +1,11 @@ +window.cli.exec['banner'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Display login banner'; + }, + run: args => { + return `Konsole ${window.cli.version} LTS ${window.cli.hostname} tty1\n\n${window.cli.hostname} login: ${window.cli.user}\npassword:\n\n`; + } +} diff --git a/src/modules/konsole/commands/cd.js b/src/modules/konsole/commands/cd.js new file mode 100644 index 0000000..14997e5 --- /dev/null +++ b/src/modules/konsole/commands/cd.js @@ -0,0 +1,15 @@ +window.cli.exec['cd'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Clear console output'; + }, + run: args => { + const path = window.cli.fs(args[0]); + if(!path) throw new Error(`cd: \'${args[0]}\': No such file or directory`) + + window.cli.pwd = window.cli.path(args[0]); + window.cli._prompt.innerText = window.cli._buildPrompt(); + } +} diff --git a/src/modules/konsole/commands/clear.js b/src/modules/konsole/commands/clear.js new file mode 100644 index 0000000..2342a66 --- /dev/null +++ b/src/modules/konsole/commands/clear.js @@ -0,0 +1,11 @@ +window.cli.exec['clear'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Clear console output'; + }, + run: args => { + setTimeout(() => window.cli._output.innerHTML = '', 1); + } +} diff --git a/src/modules/konsole/commands/date.js b/src/modules/konsole/commands/date.js new file mode 100644 index 0000000..2c62321 --- /dev/null +++ b/src/modules/konsole/commands/date.js @@ -0,0 +1,11 @@ +window.cli.exec['date'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Get current date & time'; + }, + run: args => { + return new Date().toLocaleString(); + } +} diff --git a/src/modules/konsole/commands/echo.js b/src/modules/konsole/commands/echo.js new file mode 100644 index 0000000..ac0a8a2 --- /dev/null +++ b/src/modules/konsole/commands/echo.js @@ -0,0 +1,11 @@ +window.cli.exec['echo'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Output text to console'; + }, + run: args => { + return args.join(' '); + } +} diff --git a/src/modules/konsole/commands/exit.js b/src/modules/konsole/commands/exit.js new file mode 100644 index 0000000..524dc00 --- /dev/null +++ b/src/modules/konsole/commands/exit.js @@ -0,0 +1,16 @@ +window.cli.exec['exit'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'End session'; + }, + run: args => { + setTimeout(() => { + window.cli._history = []; + window.cli._index = 0; + window.cli._output.innerHTML = '' + window.cli.stdOut(window.cli.exec['banner'].run()); + }, 1); + } +} diff --git a/src/modules/konsole/commands/help.js b/src/modules/konsole/commands/help.js new file mode 100644 index 0000000..33101ef --- /dev/null +++ b/src/modules/konsole/commands/help.js @@ -0,0 +1,12 @@ +window.cli.exec['help'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Display all commands'; + }, + run: args => { + return `Konsole v${window.cli.version} - an experimental bash emulator written in JavaScript\nCreated By: Zakary Timson\n\n` + + Object.keys(window.cli.exec).map(command => `${command} - ${window.cli.exec[command].help()}`).join('\n'); + } +} diff --git a/src/modules/konsole/commands/hostname.js b/src/modules/konsole/commands/hostname.js new file mode 100644 index 0000000..e4a92ed --- /dev/null +++ b/src/modules/konsole/commands/hostname.js @@ -0,0 +1,11 @@ +window.cli.exec['hostname'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Get computer hostname'; + }, + run: args => { + return window.cli.hostname; + } +} diff --git a/src/modules/konsole/commands/ls.js b/src/modules/konsole/commands/ls.js new file mode 100644 index 0000000..19e1896 --- /dev/null +++ b/src/modules/konsole/commands/ls.js @@ -0,0 +1,13 @@ +window.cli.exec['ls'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Display directory contents'; + }, + run: args => { + const target = window.cli.fs(args[0]); + if(!target) throw new Error(`ls: cannot access \'${args[0]}\': No such file or directory`) + return Object.keys(target).reduce((acc, p) => acc + `${p}\n`, ''); + } +} diff --git a/src/modules/konsole/commands/man.js b/src/modules/konsole/commands/man.js new file mode 100644 index 0000000..74bccc2 --- /dev/null +++ b/src/modules/konsole/commands/man.js @@ -0,0 +1,11 @@ +window.cli.exec['man'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'View command\'s manual'; + }, + run: args => { + return window.cli.exec[args[0]].help(); + } +} diff --git a/src/modules/konsole/commands/mkdir.js b/src/modules/konsole/commands/mkdir.js new file mode 100644 index 0000000..930cbce --- /dev/null +++ b/src/modules/konsole/commands/mkdir.js @@ -0,0 +1,12 @@ +window.cli.exec['mkdir'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Create new directory'; + }, + run: args => { + if(!args[0]) throw new Error('mkdir: missing operand'); + window.cli.fs(args[0], {}); + } +} diff --git a/src/modules/konsole/commands/pwd.js b/src/modules/konsole/commands/pwd.js new file mode 100644 index 0000000..2cb80f0 --- /dev/null +++ b/src/modules/konsole/commands/pwd.js @@ -0,0 +1,11 @@ +window.cli.exec['pwd'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Get present working directory'; + }, + run: args => { + return window.cli.pwd; + } +} diff --git a/src/modules/konsole/commands/rm.js b/src/modules/konsole/commands/rm.js new file mode 100644 index 0000000..cab3bb8 --- /dev/null +++ b/src/modules/konsole/commands/rm.js @@ -0,0 +1,12 @@ +window.cli.exec['rm'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Delete file or directory'; + }, + run: args => { + if(!args[0]) throw new Error('rm: missing operand'); + window.cli.fs(args[0], null); + } +} diff --git a/src/modules/konsole/commands/shower-thoughts.js b/src/modules/konsole/commands/shower-thoughts.js new file mode 100644 index 0000000..0ff15b3 --- /dev/null +++ b/src/modules/konsole/commands/shower-thoughts.js @@ -0,0 +1,23 @@ +window.cli.exec['shower-thought'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Random shower thought'; + }, + run: args => { + const motd = [ + 'Why do kamikaze pilots wear helmets?', + 'How are giraffes real, but unicorns made up', + 'When you are a kid you don\'t realize you are also watching your parents grow up', + 'Some one at Google was like "Yea, just have someone drive down every road on earth!"', + 'The number of people older than you never goes up', + 'When you brush your teeth you are cleaning your skeleton', + 'Pregnancy is like a group project where one person get\'s stuck with all the work', + 'If the universe wasn\'t infinite it would be even scarier', + 'Either we are alone in the universe or we are not. both are terrifying', + 'The object of golf is to play the least amount of golf.' + ]; + return motd[~~(Math.random() * motd.length)]; + } +} diff --git a/src/modules/konsole/commands/whoami.js b/src/modules/konsole/commands/whoami.js new file mode 100644 index 0000000..0837f08 --- /dev/null +++ b/src/modules/konsole/commands/whoami.js @@ -0,0 +1,11 @@ +window.cli.exec['whoami'] = { + autocomplete: () => { + return []; + }, + help: () => { + return 'Get current user account'; + }, + run: args => { + return window.cli.user; + } +} diff --git a/src/modules/konsole/index.js b/src/modules/konsole/index.js new file mode 100644 index 0000000..290bd5e --- /dev/null +++ b/src/modules/konsole/index.js @@ -0,0 +1,19 @@ +import './konsole.js'; +import './konsole.css'; + +// CLI Commands +import './commands/banner.js'; +import './commands/cd.js' +import './commands/clear.js'; +import './commands/date.js'; +import './commands/echo.js'; +import './commands/exit.js'; +import './commands/help.js'; +import './commands/hostname.js'; +import './commands/ls.js'; +import './commands/man.js'; +import './commands/mkdir.js'; +import './commands/pwd.js'; +import './commands/rm.js'; +import './commands/shower-thoughts.js'; +import './commands/whoami.js'; diff --git a/src/modules/konsole/konsole.css b/src/modules/konsole/konsole.css new file mode 100644 index 0000000..0cf087f --- /dev/null +++ b/src/modules/konsole/konsole.css @@ -0,0 +1,39 @@ +.cli-container { + padding: 1em; + background: #333; + font-family: monospace !important; + overflow-y: auto; + min-height: 150px; + max-height: 300px; +} + +.cli-stdout { + flex-grow: 1; + color: #0f0; +} + +.cli-stdout-line { + padding: 0; + margin: 0; + min-height: 1em; +} + +.cli-stdin { + display: flex; +} + +.cli-stdin-prompt { + padding-right: 0.5em; + text-wrap: nowrap; + color: #0f0; +} + +.cli-stdin-input { + border: none; + outline: none; + font-size: 1em; + background-color: rgba(0, 0, 0, 0); + color: #0f0; + flex-grow: 1; + padding: 0; +} diff --git a/src/modules/konsole/konsole.js b/src/modules/konsole/konsole.js new file mode 100644 index 0000000..b06d9d0 --- /dev/null +++ b/src/modules/konsole/konsole.js @@ -0,0 +1,157 @@ +window.cli = { + // Element references + _input: null, + _parent: null, + _prompt: null, + _output: null, + + // CLI State + _history: [], + _index: 0, + pwd: '/', + hostname: 'virtual', + env: {}, + exec: {}, + filesystem: {}, + user: 'root', + version: '0.3.0', + + _buildPrompt: () => `${window.cli.user}@${window.cli.hostname}:${window.cli.pwd}${window.cli.user == 'root' ? '#' : '$'}`, + + build: (elementId) => { + window.cli._parent = document.querySelector(elementId); + if(!window.cli._parent) + throw new Error(`Could not create konsole, element "${elementId}" does not exist`); + + window.cli._parent.innerHTML = ` +
+
+
+ + +
+
`; + + window.cli._input = document.querySelector(elementId + ' .cli-stdin-input'); + window.cli._prompt = document.querySelector(elementId + ' .cli-stdin-prompt'); + window.cli._output = document.querySelector(elementId + ' .cli-stdout'); + window.cli._input.addEventListener('keyup', (e) => { + if(e.key == "Enter") { + window.cli.disable(); + if(!!window.cli._input.value) { + window.cli._history.push(window.cli._input.value); + window.cli._index = window.cli._history.length; + window.cli.stdIn(window.cli._input.value) + } + window.cli._input.value = ''; + window.cli.enable(); + } else if(e.key == 'Up' || e.key == 'ArrowUp') { + if(window.cli._index > 0) window.cli._index--; + window.cli._input.value = window.cli._index == window.cli._history.length ? '' : window.cli._history[window.cli._index]; + setTimeout(() => { + const end = window.cli._input.value.length; + window.cli._input.setSelectionRange(end, end); + window.cli._input.focus(); + }, 1) + } else if(e.key == 'Down' || e.key == 'ArrowDown') { + if(window.cli._index < window.cli._history.length) window.cli._index++; + window.cli._input.value = window.cli._index == window.cli._history.length ? '' : window.cli._history[window.cli._index]; + setTimeout(() => { + const end = window.cli._input.value.length; + window.cli._input.setSelectionRange(end, end); + window.cli._input.focus(); + }, 1) + } + }); + setTimeout(() => window.cli.stdOut(window.cli.exec['banner'].run()), 1); + }, + disable: () => { + window.cli._input.disabled = true; + window.cli._prompt.style.visibility = 'hidden'; + }, + enable: () => { + window.cli._input.disabled = false; + window.cli._input.focus(); + window.cli._prompt.style.visibility = 'visible'; + }, + path: (path=window.cli.pwd) => { + let p = path[0] == '/'? path : (window.cli.pwd + (window.cli.pwd.endsWith('/') ? '' : '/') + path.replace('./', '')) + .replaceAll('//', '/'); + const parts = p.split('/').filter(p => !!p); + for(let i = 0; i < parts.length; i++) { + if(parts[i] == '..') { + i--; + parts.splice(i, 2); + i--; + } + } + return '/' + (parts.length ? parts.join('/') : ''); + }, + fs: (path, set) => { + return window.cli.path(path).split('/').filter(p => !!p).reduce((t, p, i, arr) => { + if(!t?.hasOwnProperty(p)) { + if(set == undefined) return undefined; + t[p] = {}; + } + if(set !== undefined && i == arr.length - 1) { + if(set == null) delete t[p]; + else t[p] = set; + } + return t[p]; + }, window.cli.filesystem); + }, + stdErr: (text) => { + const p = document.createElement('p'); + p.classList.add('cli-stdout-line'); + p.classList.add('cli-stdout-error'); + p.innerText = text; + window.cli._output.appendChild(p); + }, + stdIn:(command, suppress=false) => { + (Array.isArray(command) ? command.join(' ') : command).split(';').filter(c => !!c).forEach(c => { + const parts = c.match(/(?:[^\s"]+|"[^"]*")+/g); + if(!parts) return; + + const exec = window.cli.exec[parts[0]]; + if(!exec?.run) { + if(!suppress) window.cli.stdErr(`${window.cli._buildPrompt()} ${command}\n${parts[0]}: command not found`); + } else { + try { + const args = parts.slice(1).map(a => (a[0] == '"' || a[0] == "'") ? a.slice(1, -1) : a); + const out = exec.run(args); + if(!suppress) window.cli.stdOut(`${window.cli._buildPrompt()} ${command}${out ? '\n' + out : ''}`); + } catch(err) { + console.error(err); + if(!suppress) { + window.cli._output.removeChild(window.cli._output.children[window.cli._output.children.length - 1]); + window.cli.stdErr(`${window.cli._buildPrompt()} ${command}\n${err.message || `${parts[0]}: exited with a non-zero status`}`); + } + } + } + }); + }, + stdOut: (text='', html=false) => { + const p = document.createElement('p'); + p.classList.add('cli-stdout-line'); + p[html ? 'innerHTML' : 'innerText'] = text; + window.cli._output.appendChild(p); + }, + type: (text, speed=150) => { + let counter = 0; + return new Promise(res => { + let typing = setInterval(() => { + if(counter < text.length) { + window.cli._input.value += text[counter]; + } else { + clearInterval(typing); + setTimeout(() => { + window.cli.stdIn(text); + window.cli._input.value = ''; + res(); + }, 750); + } + counter++; + }, speed); + }); + } +};