| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306 |
- function pgsh(ev) {
- var self = this
- /**
- * Terminal UI/Shell Entry Point
- */
- ev.on('cmd_entered', function(input) {
- var args = input.trim().split(' ')
- // Use the first argument as a command, or the value of `active`.
- var command = self.active ? self.active : args.shift()
- if (command in self.commands) {
- self[command](args)
- } else if (command) {
- show(command + ' not found')
- }
- })
- /**
- * Key functions
- */
- ev.on('mount', function() {
- document.getElementById(ev.id).onkeydown = function(e) {
- var code = e.keyCode || e.which
- // Tab for file path completion.
- if (code == 9) {
- var input = ev.tags['command-line'].command.value.trim().split(' ')
- var command = input.shift()
- if (['cat', 'cd', 'ls'].indexOf(command) != -1) {
- var args = input.join(' ').trim()
- var isFile = (command == 'cat') ? true : false;
- var path = completePath(args, isFile)
- if (path) { ev.trigger('cmd_set', command + ' ' + path) }
- }
- e.preventDefault()
- }
- }
- })
- /**
- * Variables and Setup
- */
- var getHome = function() { return self.su_active ? '/root' : '/home/pgs' }
- this.cwd = getHome()
- var getPrompt = function() {
- if (self.su_active) {
- return '' +
- '<span style="color:#dc322f">root </span>' +
- '<span style="color:#b58900">' + self.cwd + ' </span>' +
- '<span style="color:#268bd2">% </span>'
- }
- return '' +
- '<span style="color:#d33682">pgs </span>' +
- '<span style="color:#b58900">' + self.cwd + ' </span>' +
- '<span style="color:#2aa198">$ </span>'
- }
- this.prompt = getPrompt()
- this.welcome = '' +
- 'Linux parsleygardens.net 3.4.5-6-7-i286 #8 PGS Vimputer' +
- '3.4.56-7 i286\n\n' +
- '~ Welcome to Parsley Gardens! ~\n' +
- '"He maketh me to lie down in green pa..."\n\n' +
- 'Type `<strong>help</strong>` for list of commands\n\n'
- this.tree = pgfs
- /**
- * Commands
- */
- this.commands = {
- 'about': { order: 1, help: 'Author Information' },
- 'cat': { order: 2, help: 'Con(cat)enate the contents of a file' },
- 'cd': { order: 2, help: 'Change folder/directory' },
- 'clear': { order: 2, help: 'Clears the screen' },
- 'exit': { order: 2, help: 'Leave the current context' },
- 'hello': { order: 2, help: 'Say hello to the computer\nUsage: hello [name]' },
- 'help': { order: 1, help: 'List commands or view information for one\nUsage: help [command]' },
- 'ls': { order: 2, help: 'List folder contents' },
- 'magic': { order: 1, help: 'The Website of an Artist' },
- 'pwd': { order: 2, help: 'Show the current working directory' },
- 'question': { order: 1, help: 'Displays a question' },
- 'search': { order: 2, help: 'Search the Web (with a Duck)\nUsage: search [query]' },
- 'su': { order: 2, help: 'Gain Phenomenal Cosmic Power' },
- 'version': { order: 1, help: 'Display shell information' }
- }
- this.about = function(args) { self.cat(['/home/pgs/about.md']) }
- this.magic = function(args) { self.cat(['/home/pgs/magic.txt']) }
- this.cat = function(args) {
- var arg = args.join(' ').trim()
- var path = resolveAbsPath(arg)
- if (pathExists(path, true)) {
- var content = getContents(path)
- if (path.search('.md|.sh') != -1) {
- content = hljs.highlightAuto(content).value
- }
- show('\n' + content + '\n\n')
- } else {
- show("cat: " + arg + ": no such file")
- }
- }
- this.cd = function(args) {
- var arg = args.join(' ').trim()
- arg = arg ? arg : getHome()
- var path = resolveAbsPath(arg)
- if (pathExists(path)) {
- self.cwd = path
- ev.trigger('prompt_set', getPrompt())
- } else {
- show("cd: " + arg + ": no such directory")
- }
- }
- this.clear = function(args) { ev.trigger('disp_clear') }
- this.exit = function(args) {
- if (self.su_active) {
- self.su_active = false
- ev.trigger('prompt_set', getPrompt())
- return
- }
- show('Close browser window to exit')
- }
- this.hello = function(args) {
- address = args.join(' ').trim()
- if (address.length == 0) {
- show('Hello to you too')
- } else if (address == 'pgsh') {
- show('Hello human')
- } else {
- show('My name is not "' + address + '"')
- }
- }
- this.help = function(args) {
- command = args.join(' ').trim()
- if (command in self.commands) {
- show(self.commands[command].help)
- } else if (command) {
- show('No information for: ' + command)
- } else {
- var main = []
- var other = []
- for (var name in self.commands) {
- if (self.commands[name].order == 1) {
- main.push(name)
- } else {
- other.push(name)
- }
- }
- show('\nAvailable commands:\n\n' +
- '* ' + main.sort().join(' ') + '\n\n' +
- '* ' + other.sort().join(' ') + '\n\n' +
- '`help [command]` for more information.')
- }
- }
- this.ls = function(args) {
- var arg = args.join(' ').trim()
- var folder = arg || self.cwd
- var path = resolveAbsPath(folder)
- if (pathExists(path)) {
- var contents = getContents(path)
- var dstat = 'drwxr-xr-x <span style="color:#268bd2">'
- var fstat = '-rw-r--r-- '
- var items = []
- for (var item in contents) {
- var prefix = (typeof contents[item] === 'string') ? fstat : dstat
- var suffix = (typeof contents[item] === 'string') ? '' : '</span>'
- items.push(prefix + item + suffix)
- }
- items.unshift(dstat + '..</span>')
- items.unshift('total ' + items.length)
- show(items.join('\n'))
- } else {
- show("ls: " + args + ": no such directory")
- }
- }
- this.pwd = function(args) { show(self.cwd) }
- this.question = function(args) {
- var questions = [
- 'Isn\'t <a href="https://www.youtube.com/watch?v=dQw4w9WgXcQ"' +
- ' target="_blank">this song</a> the best?',
- '1 + 2 = ?',
- 'Am I a sandwich?',
- 'Where were you at 3:15am on April 14th?',
- "Don't you mean prism?",
- 'Butts twelve by pies?',
- 'I say there, Monstrosity. Do you know the times?',
- 'What is the name of the spaces between the teeth of a comb?',
- 'Why are you dressed up like Ship\'s Captain?'
- ]
- var rand = Math.floor(Math.random() * questions.length);
- show(questions[rand])
- }
- this.search = function(args) {
- if (!args.join(' ').trim()) { return show(self.commands.search.help) }
- ev.trigger('prompt_hide')
- show('Searching for "' + args.join(' ') + '" in new window...')
- setTimeout(function() {
- window.open('https://duckduckgo.com/?q=' + args.join('+'), '_blank')
- ev.trigger('prompt_show')
- }, 1000)
- }
- this.su = function(args) {
- if (self.su_active !== true) {
- self.su_active = true
- if (!self.su_warned) {
- self.su_warned = true
- show('\n\n' +
- 'We trust you have received the usual lecture from the ' +
- 'local System Administrator.\n' +
- 'It usually boils down to these three things:\n\n' +
- ' #1) Respect the privacy of others.\n' +
- ' #2) Think before you type.\n' +
- ' #3) With great power comes great\n\n')
- }
- ev.trigger('prompt_set', getPrompt())
- }
- }
- this.version = function(args) {
- show('Parsley Gardens Shell (pgsh) 1.1.0\nBuilt with: ' +
- '<a target="_blank" href="http://riotjs.com">Riot</a> ' +
- '<a target="_blank" href="https://skeleton-framework.github.io">Skeleton</a> ' +
- '<a target="_blank" href="https://highlightjs.org">highlight.js</a>')
- }
- /**
- * Helper Functions
- */
- var show = function(text) { ev.trigger('disp_add', text) }
- var set = function(text) { ev.trigger('disp_set', text) }
- // Calculate a destination's path with respect to the current folder.
- var resolveAbsPath = function(dest) {
- var parts = dest.trim().split('/')
- var absolute = dest.substring(0, 1) == '/' || self.cwd == '/'
- var path = absolute ? [''] : self.cwd.split('/')
- parts.forEach(function(part) {
- if (part == '..' && path.length > 1) { path.pop() }
- if (part != '..' && part) { path.push(part) }
- })
- return (path.length > 1) ? path.join('/') : '/'
- }
- // Check if a path exists in the tree.
- var pathExists = function(path, isFile) {
- // Old way of defining default values, for Safari.
- var isFile = (typeof isFile !== 'undefined') ? isFile : false;
- var parts = path.trim().split('/')
- var fname = isFile ? parts.pop() : ''
- var tree = self.tree
- for (var i = 0; i < parts.length; i++) {
- var part = parts[i]
- if (!part) {
- continue
- }
- if (!(tree.hasOwnProperty(part) && typeof tree[part] === 'object')) {
- return false
- }
- tree = tree[part]
- }
- if (isFile && !(tree.hasOwnProperty(fname) && typeof tree[fname] === 'string')) {
- return false
- }
- return true
- }
- // Return the contents of a given path.
- var getContents = function(path) {
- var parts = path.trim().split('/')
- var tree = self.tree
- parts.forEach(function(part) {
- if (part) { tree = tree[part] }
- })
- // Sort JS object. Not a great way, but more compatible.
- if (typeof tree === 'object') {
- var keys = []
- for (key in tree) {
- keys.push(key)
- }
- keys.sort()
- var temp = {}
- keys.forEach(function(key) {
- temp[key] = tree[key]
- })
- tree = temp
- }
- return tree
- }
- // Complete a given file path string based on the current tree.
- var completePath = function(input, isFile) {
- // Extract file fragment and get actual path.
- var slash = input.lastIndexOf('/') + 1
- var frag = input.substring(slash)
- var base = input.substring(0, slash)
- var path = resolveAbsPath(base)
- // Complete fragments.
- if (pathExists(path)) {
- var contents = getContents(path)
- var found = ''
- for (var name in contents) {
- if (!isFile && typeof contents[name] === 'string') { continue }
- if (!frag) { found = name; break }
- if (name.indexOf(frag) == 0) { found = name; break }
- }
- var end = (typeof contents[found] === 'object') ? '/' : ''
- return base + found + end
- }
- return ''
- }
- }
|