| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154 |
- <terminal-ui id={ id } tabindex='1'>
- <display-buffer welcome={ welcome } events={ this } />
- <command-line prompt={ prompt } events={ this } />
- <style>
- terminal-ui { outline: none; }
- terminal-ui * { padding: 0; margin: 0; line-height: normal; font-size: 100%; }
- </style>
- /**
- * Create a new shell object using the class name given to terminal-ui.
- * The terminal-ui object is itself passed to this shell class.
- * The terminal-ui object, being an Observable, allows the shell object and
- * other tags to fire events to each other.
- */
- var shell = window[opts.shell] ? new window[opts.shell](this) : {}
- this.welcome = shell.welcome || opts.welcome
- this.prompt = shell.prompt || opts.prompt
- this.id = 'term-' + Math.floor(Math.random() * 10000)
- </terminal-ui>
- <display-buffer>
- <div each={ output }>
- <raw-html content={ content } />
- </div>
- var ev = opts.events, self = this
- this.contexts = {}
- this.output = this.contexts['default'] = []
- this.on('mount', function() { this.add(opts.welcome) })
- ev.on('disp_add', function(text) { self.add(text) })
- ev.on('disp_set', function(text) {
- if (text) {
- self.clear()
- self.add(text)
- }
- })
- ev.on('disp_clear', function() { self.clear() })
- ev.on('context_swap', function(name) {
- name = name || 'default'
- if (!(name in self.contexts)) {
- self.contexts[name] = []
- }
- self.update({ output: self.contexts[name] })
- })
- add(text) {
- if (text) {
- this.output.push({ 'content': text })
- this.update()
- }
- }
- clear() {
- this.output.length = 0
- this.update()
- }
- </display-buffer>
- <command-line>
- <form autocomplete='off' onsubmit={ process } show={ visible }>
- <raw-html name='lhs' content={ prompt } show={ prompt_visible }>
- </raw-html><input type='text' ref='command' />
- </form>
- <style>
- command-line input[ref='command'],
- command-line input[ref='command']:hover,
- command-line input[ref='command']:focus {
- padding: 0; margin: 0; line-height: normal; font-size: 100%;
- background-color: transparent; border: none; outline: none;
- height: auto; width: 70%;
- display: inline;
- }
- </style>
- var ev = opts.events, self = this
- this.contexts = {}
- this.current = 'default'
- this.contexts[this.current] = {}
- this.visible = this.prompt_visible = true
- this.prompt = opts.prompt || '$ '
- this.on('mount', function() { this.refs.command.focus() })
- ev.on('prompt_set', function(text) { self.prompt = text })
- ev.on('prompt_hide', function() { self.update({ prompt_visible: false }) })
- ev.on('prompt_show', function() { self.update({ prompt_visible: true }) })
- ev.on('cmd_add', function(text) { self.refs.command.value += text })
- ev.on('cmd_set', function(text) { self.refs.command.value = text })
- ev.on('cli_hide', function() { self.update({ visible: false }) })
- ev.on('cli_show', function() {
- self.update({ visible: true })
- self.refs.command.focus()
- })
- ev.on('context_swap', function(name) {
- name = name || 'default'
- // Initialise a new context if a given name does not already exist.
- if (!(name in self.contexts)) {
- self.contexts[name] = { visible: true, prompt: '', prompt_visible: true }
- }
- // Save current values and load target context.
- ['visible', 'prompt', 'prompt_visible'].forEach(function(p) {
- self.contexts[self.current][p] = self[p]
- self[p] = self.contexts[name][p]
- })
- // Update the display.
- self.current = name
- if (self.visible) {
- self.refs.command.focus()
- }
- })
- process(event) {
- var prompt = this.prompt_visible ? this.prompt : ''
- var command = this.encode(this.refs.command.value)
- ev.trigger('disp_add', prompt + command + '\n')
- ev.trigger('cmd_entered', command)
- this.refs.command.value = ''
- // Refocus to scroll display and keep input in view.
- this.refs.command.blur()
- this.refs.command.focus()
- event.preventDefault()
- }
- encode(text) {
- return text.replace(/&/g,'&').replace(/</g,'<').replace(/>/g,'>')
- }
- </command-line>
- <raw-html>
- <span></span>
- <style>
- raw-html { white-space: pre-wrap }
- </style>
- this.on('mount', function() { this.write() })
- this.on('update', function() { this.write() })
- write() { this.root.innerHTML = opts.content }
- </raw-html>
|