From a43fc2789c23e4d0d72703a5ee7bcc7f02b9c3e9 Mon Sep 17 00:00:00 2001 From: Jelle De Loecker Date: Wed, 20 Jan 2016 11:14:45 +0100 Subject: [PATCH] Add beginnings of autocomplete functionality, refs #3 --- CHANGELOG.md | 2 + README.md | 3 +- lib/init.js | 193 +++++++++++++++++++++++++++++++++++++++++++++++++-- 3 files changed, 193 insertions(+), 5 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index f016cc3..c9aa1e7 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,7 @@ ## 0.1.5 (WIP) +* Add autocomplete (basic for now) + ## 0.1.4 (2016-01-20) * Improve multiline string support diff --git a/README.md b/README.md index 8ad8219..e574e65 100644 --- a/README.md +++ b/README.md @@ -12,12 +12,13 @@ A curses/blessed-based console, inspired by the developer tools in Webkit/Blink. ## Features * Interactive command line, that always has focus +* Autocomplete * Output is clickable. Variables can be inspected, just like in the browser ## Todo +* Use editor-widget for CLI: https://github.com/slap-editor/editor-widget * Improve command-line eval/vm situation -* Fix bugs & screen glitches * Improve colouring * Improve multiline support * Filename & line information per log line diff --git a/lib/init.js b/lib/init.js index f0dca47..6c79e49 100644 --- a/lib/init.js +++ b/lib/init.js @@ -14,9 +14,11 @@ var Blast = require('protoblast')(false), // Protoblast without native mods * * @author Jelle De Loecker * @since 0.1.0 - * @version 0.1.4 + * @version 0.1.5 */ -JanewayClass = Blast.Collection.Function.inherits('Informer', function Janeway() {}); +JanewayClass = Blast.Collection.Function.inherits('Informer', function Janeway() { + this.open_popups = {}; +}); /** * Scrolldown on new data (true by default) @@ -462,6 +464,137 @@ JanewayClass.setMethod(function scrollAlong(or_render) { } }); +/** + * Show a popup + * + * @author Jelle De Loecker + * @since 0.1.5 + * @version 0.1.5 + * + * @param {String} id The unique id (only 1 can be open at a time) + * @param {Object} options + * + * @return {ListBox} + */ +JanewayClass.setMethod(function popup(id, options) { + + var list; + + if (!options) { + if (this.open_popups[id]) { + this.open_popups[id].destroy(); + } + + return; + } + + if (!options.position) { + options.position = {}; + } + + if (options.position.bottom == null) { + options.position.bottom = 2; + } + + if (options.position.height == null) { + options.position.height = 6; + } + + if (this.open_popups[id]) { + this.open_popups[id].destroy(); + } + + // Create a new list + list = this.blessed.list({ + //bottom: 2, + position: options.position, + width: '100%', + items: options.items, + mouse: true, // Allow selecting items with the mouse + scrollbar: { + bg: 'green' + }, + border: { + type: 'line' + }, + shadow: true, + style: { + bg: 'blue', + fg: 'white' + } + }); + + // Store the popup under its unique id + this.open_popups[id] = list; + + // Add it to the screen + this.screen.append(list); + + // Make sure it's in the front + list.setFront(); + + // Render the screen + this.screen.render(); + + return list; +}); + +/** + * Show the autocomplete + * + * @author Jelle De Loecker + * @since 0.1.5 + * @version 0.1.5 + * + * @param {String} cmd The current content of the CLI + * @param {Object} key The last key pressed + */ +JanewayClass.setMethod(function autocomplete(cmd, key) { + + var pieces, + target, + items, + last, + left, + list, + key; + + if (!cmd && !key) { + return this.autocomplete_list = this.popup('autocomplete', false); + } + + this.autocomplete_prefix = null; + pieces = cmd.split('.'); + items = []; + left = 1 + cmd.length; + + if (pieces.length == 1) { + target = global; + last = cmd; + } else { + last = pieces.pop(); + target = Blast.Bound.Object.path(global, pieces); + + this.autocomplete_prefix = pieces.join('.') + '.'; + } + + if (target) { + for (key in target) { + if (!last || Blast.Bound.String.startsWith(key, last)) { + items.push(key); + } + } + } + + if (cmd.trim() && items.length) { + list = this.popup('autocomplete', {position: {left: left, height: 6}, items: items}); + } else { + list = this.popup('autocomplete', false); + } + + this.autocomplete_list = list; +}); + /** * Start Janeway * @@ -528,7 +661,6 @@ JanewayClass.setMethod(function start() { }, //inputOnFocus: true, mouse: true - //keys: true }); output = blessed.box({ @@ -549,6 +681,14 @@ JanewayClass.setMethod(function start() { } }); + // Store elements in the object + this.blessed = blessed; + this.screen = screen; + this.output = output; + this.bottom = bottom; + this.form = form; + this.cli = cli; + // Create the LogList instance logList = new Janeway.LogList(this, screen, output); this.logList = logList; @@ -731,7 +871,7 @@ JanewayClass.setMethod(function start() { * * @author Jelle De Loecker * @since 0.1.0 - * @version 0.1.4 + * @version 0.1.5 */ cli.on('keypress', function onKeypress(e, key) { @@ -740,6 +880,8 @@ JanewayClass.setMethod(function start() { errorLine, evalLine, scope, + path, + temp, cmd; if (key.name == 'pagedown') { @@ -747,6 +889,23 @@ JanewayClass.setMethod(function start() { } else if (key.name == 'pageup') { that.scroll(-20); } else if (key.name == 'enter') { + + if (that.autocomplete_list) { + + // Get the selected item + temp = that.autocomplete_list.getItem(that.autocomplete_list.selected); + + // Get the path before the last dot + path = that.autocomplete_prefix || ''; + + if (temp) { + cli.setValue(path + temp.content); + that.autocomplete(); + } + + return; + } + cmd = cli.getValue().trim(); // Return if the cmd is empty @@ -801,6 +960,31 @@ JanewayClass.setMethod(function start() { // Scroll along if needed that.scrollAlong(); }); + } else { + cmd = cli.getValue(); + + if (key.code) { + // Ignore keys with codes + + if (that.autocomplete_list) { + if (key.name == 'up') { + that.autocomplete_list.up(1); + that.autocomplete_list.render(); + screen.render(); + } else if (key.name == 'down') { + that.autocomplete_list.down(1); + screen.render(); + } + } + + return; + } else if (key.name === 'backspace') { + cmd = cmd.slice(0, -1); + } else { + cmd += e; + } + + that.autocomplete(cmd, key); } }); @@ -809,6 +993,7 @@ JanewayClass.setMethod(function start() { screen.append(output); bottom.append(form); form.append(cli); + screen.render(); // Quit on Escape, q, or Control-C.