Last active
February 27, 2019 02:31
-
-
Save camwhite/d17de0a41dcb87d235b386106386f746 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| class TermStream extends Duplex { | |
| constructor(vm) { | |
| super() | |
| this.result = '' | |
| this.$terminal = vm.$terminal | |
| this.$vm = vm | |
| this.encoding = vm.encoding || 'utf-8' | |
| if (!this.$terminal) { | |
| throw new TypeError('VueTerm instance only') | |
| } | |
| this.$terminal.on('data', data => { | |
| this.result += data | |
| this.write(Buffer.from(data, this.encoding)) | |
| }) | |
| this.$terminal.on('keydown', ({ code }) => { | |
| if (code === 'Enter') { | |
| this.push(Buffer.from(this.result, this.encoding)) | |
| this.$terminal.write('\n') | |
| this._flush() | |
| } | |
| if (code === 'Backspace') { | |
| this.$terminal.write('\b \b') | |
| } | |
| }) | |
| } | |
| _write(chunk, encoding, callback) { | |
| if (Buffer.isBuffer(chunk)) { | |
| chunk = chunk.toString(this.encoding) | |
| } | |
| this.$terminal.write(chunk) | |
| callback() | |
| } | |
| _final(callback) { | |
| this.$vm.$emit('final') | |
| if (callback) callback() | |
| } | |
| _flush() { | |
| this.result = '' | |
| this.push(Buffer.from(this.result, this.encoding)) | |
| } | |
| _read(size) { | |
| return this.result | |
| } | |
| } |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| <template> | |
| <div class="xterm"></div> | |
| </template> | |
| <script> | |
| import { Duplex } from 'stream' | |
| import { mapState } from 'vuex' | |
| import { Terminal } from 'xterm' | |
| import { fit } from 'xterm/lib/addons/fit/fit' | |
| import figlet from 'figlet' | |
| import 'xterm/dist/xterm.css' | |
| class TermStream extends Duplex { | |
| constructor(vm) { | |
| super() | |
| this.result = '' | |
| this.$terminal = vm.$terminal | |
| this.$vm = vm | |
| this.encoding = vm.encoding || 'utf-8' | |
| if (!this.$terminal) { | |
| throw new TypeError('xterm instance only') | |
| } | |
| this.$terminal.on('data', data => { | |
| this.result += data | |
| this.write(Buffer.from(data, this.encoding)) | |
| }) | |
| this.$terminal.on('keydown', ({ code }) => { | |
| if (code === 'Enter') { | |
| this.push(Buffer.from(this.result, this.encoding)) | |
| this.$terminal.write('\n') | |
| this._flush() | |
| } | |
| if (code === 'Backspace') { | |
| this.$terminal.write('\b \b') | |
| } | |
| }) | |
| } | |
| _write(chunk, encoding, callback) { | |
| if (Buffer.isBuffer(chunk)) { | |
| chunk = chunk.toString(this.encoding) | |
| } | |
| this.$terminal.write(chunk) | |
| callback() | |
| } | |
| _final(callback) { | |
| this.$vm.$emit('final') | |
| if (callback) callback() | |
| } | |
| _flush() { | |
| this.result = '' | |
| this.push(Buffer.from(this.result, this.encoding)) | |
| } | |
| _read(size) { | |
| return this.result | |
| } | |
| } | |
| export default { | |
| name: 'prompt', | |
| data() { | |
| return { | |
| intro: '' | |
| } | |
| }, | |
| computed: { | |
| ...mapState(['currentUser']) | |
| }, | |
| async mounted() { | |
| this.intro = await this.onFiglet( | |
| `${this.currentUser.name}'s terminal` | |
| ) | |
| const term = new Terminal() | |
| term.open(this.$el, true) | |
| fit(term) | |
| term.on('blur', () => this.$emit('blur')) | |
| term.on('focus', () => this.$emit('focus')) | |
| term.on('resize', size => fit(term)) | |
| term.write(this.intro.replace(/\n/g, '\r\n') + '\r\n') | |
| term.focus() | |
| this.$terminal = term | |
| this.$stream = new TermStream(this) | |
| this.$stream.on('data', this.onCommand) | |
| }, | |
| methods: { | |
| async onCommand(text) { | |
| text = text.toString().trim() | |
| console.log(text) | |
| if (text.startsWith('!')) { | |
| const [cmd, ...args] = text.split(' ') | |
| if (typeof args === 'array') { | |
| args = args.join(' ') | |
| } | |
| let result | |
| switch (cmd) { | |
| case '!figlet': | |
| result = await this.onFiglet(args) | |
| default: | |
| if (result) { | |
| this.$terminal.write( | |
| result.replace(/\n/g, '\r\n') + '\r\n' | |
| ) | |
| } | |
| break | |
| } | |
| } | |
| }, | |
| onFiglet(text) { | |
| return new Promise((resolve, reject) => { | |
| figlet( | |
| text, | |
| { | |
| font: 'Graffiti', | |
| horizontalLayout: 'full' | |
| }, | |
| (err, text) => { | |
| if (err) return reject(err) | |
| resolve(text) | |
| } | |
| ) | |
| }) | |
| } | |
| } | |
| } | |
| </script> | |
| <style lang="stylus" scoped></style> |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment