mirror of https://gitee.com/bigwinds/arangodb
terminal codes
This commit is contained in:
parent
58515b7894
commit
70e206fc25
|
@ -66,6 +66,10 @@ int linenoiseInstallWindowChangeHandler(void);
|
|||
/* returns type of key pressed: 1 = CTRL-C, 2 = CTRL-D, 0 = other */
|
||||
int linenoiseKeyType(void);
|
||||
|
||||
// enable reading without line buffering
|
||||
int linenoiseEnableRawMode(void);
|
||||
void linenoiseDisableRawMode(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -980,7 +980,7 @@ void linenoiseHistoryFree(void) {
|
|||
}
|
||||
}
|
||||
|
||||
static int enableRawMode(void) {
|
||||
int linenoiseEnableRawMode() {
|
||||
#ifdef _WIN32
|
||||
if (!console_in) {
|
||||
console_in = GetStdHandle(STD_INPUT_HANDLE);
|
||||
|
@ -1031,7 +1031,7 @@ fatal:
|
|||
#endif
|
||||
}
|
||||
|
||||
static void disableRawMode(void) {
|
||||
void linenoiseDisableRawMode() {
|
||||
#ifdef _WIN32
|
||||
SetConsoleMode(console_in, oldMode);
|
||||
console_in = 0;
|
||||
|
@ -1042,7 +1042,7 @@ static void disableRawMode(void) {
|
|||
}
|
||||
|
||||
// At exit we'll try to fix the terminal to the initial conditions
|
||||
static void linenoiseAtExit(void) { disableRawMode(); }
|
||||
static void linenoiseAtExit(void) { linenoiseDisableRawMode(); }
|
||||
|
||||
static int getScreenColumns(void) {
|
||||
int cols;
|
||||
|
@ -2333,10 +2333,10 @@ int InputBuffer::incrementalHistorySearch(PromptBase& pi, int startChar) {
|
|||
// job control is its own thing
|
||||
#ifndef _WIN32
|
||||
case ctrlChar('Z'): // ctrl-Z, job control
|
||||
disableRawMode(); // Returning to Linux (whatever) shell, leave raw
|
||||
linenoiseDisableRawMode(); // Returning to Linux shell, leave raw
|
||||
// mode
|
||||
raise(SIGSTOP); // Break out in mid-line
|
||||
enableRawMode(); // Back from Linux shell, re-enter raw mode
|
||||
linenoiseEnableRawMode(); // Back from Linux shell, re-enter raw mode
|
||||
{
|
||||
bufferSize = historyLineLength + 1;
|
||||
unique_ptr<char32_t[]> tempUnicode(new char32_t[bufferSize]);
|
||||
|
@ -3001,10 +3001,10 @@ int InputBuffer::getInputLine(PromptBase& pi) {
|
|||
|
||||
#ifndef _WIN32
|
||||
case ctrlChar('Z'): // ctrl-Z, job control
|
||||
disableRawMode(); // Returning to Linux (whatever) shell, leave raw
|
||||
linenoiseDisableRawMode(); // Returning to Linux shell, leave raw
|
||||
// mode
|
||||
raise(SIGSTOP); // Break out in mid-line
|
||||
enableRawMode(); // Back from Linux shell, re-enter raw mode
|
||||
linenoiseEnableRawMode(); // Back from Linux shell, re-enter raw mode
|
||||
if (!pi.write()) break; // Redraw prompt
|
||||
refreshLine(pi); // Refresh the line
|
||||
break;
|
||||
|
@ -3210,7 +3210,7 @@ char* linenoise(const char* prompt) {
|
|||
return buf8; // caller must free buffer
|
||||
}
|
||||
} else {
|
||||
if (enableRawMode() == -1) {
|
||||
if (linenoiseEnableRawMode() == -1) {
|
||||
return NULL;
|
||||
}
|
||||
InputBuffer ib(buf32, charWidths, LINENOISE_MAX_LINE);
|
||||
|
@ -3220,7 +3220,7 @@ char* linenoise(const char* prompt) {
|
|||
}
|
||||
buf32[LINENOISE_MAX_LINE] = '\0'; // make sure the buffer is always null-terminated
|
||||
int count = ib.getInputLine(pi);
|
||||
disableRawMode();
|
||||
linenoiseDisableRawMode();
|
||||
printf("\n");
|
||||
if (count == -1) {
|
||||
return NULL;
|
||||
|
@ -3398,7 +3398,7 @@ void linenoisePrintKeyCodes(void) {
|
|||
printf(
|
||||
"Linenoise key codes debugging mode.\n"
|
||||
"Press keys to see scan codes. Type 'quit' at any time to exit.\n");
|
||||
if (enableRawMode() == -1) return;
|
||||
if (linenoiseEnableRawMode() == -1) return;
|
||||
memset(quit, ' ', 4);
|
||||
while (1) {
|
||||
char c;
|
||||
|
@ -3419,7 +3419,7 @@ void linenoisePrintKeyCodes(void) {
|
|||
printf("\r"); /* Go left edge manually, we are in raw mode. */
|
||||
fflush(stdout);
|
||||
}
|
||||
disableRawMode();
|
||||
linenoiseDisableRawMode();
|
||||
}
|
||||
|
||||
#ifndef _WIN32
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
#include "Basics/ArangoGlobalContext.h"
|
||||
#include "Basics/FileUtils.h"
|
||||
#include "Basics/StringUtils.h"
|
||||
#include "Basics/terminal-utils.h"
|
||||
#include "Basics/Utf8Helper.h"
|
||||
#include "Logger/Logger.h"
|
||||
#include "ProgramOptions/ProgramOptions.h"
|
||||
|
@ -44,6 +45,10 @@
|
|||
#include "V8/v8-utils.h"
|
||||
#include "V8/v8-vpack.h"
|
||||
|
||||
extern "C" {
|
||||
#include <linenoise.h>
|
||||
}
|
||||
|
||||
using namespace arangodb;
|
||||
using namespace arangodb::basics;
|
||||
using namespace arangodb::options;
|
||||
|
@ -766,6 +771,34 @@ static void JS_StopOutputPager(
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief start the invasion
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void JS_StartFlux(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
v8::Local<v8::External> wrap = v8::Local<v8::External>::Cast(args.Data());
|
||||
V8ShellFeature* shell = static_cast<V8ShellFeature*>(wrap->Value());
|
||||
|
||||
linenoiseEnableRawMode();
|
||||
TRI_SetStdinVisibility(false);
|
||||
TRI_DEFER(
|
||||
linenoiseDisableRawMode();
|
||||
TRI_SetStdinVisibility(true););
|
||||
|
||||
|
||||
auto path = FileUtils::buildFilename(shell->startupDirectory(),
|
||||
"contrib/flux/flux.js");
|
||||
|
||||
TRI_ExecuteGlobalJavaScriptFile(isolate, path.c_str(), true);
|
||||
|
||||
TRI_V8_RETURN_UNDEFINED();
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief normalizes UTF 16 strings
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -926,6 +959,12 @@ void V8ShellFeature::initGlobals() {
|
|||
_isolate, TRI_V8_ASCII_STRING(_isolate, "SYS_STOP_PAGER"),
|
||||
v8::FunctionTemplate::New(_isolate, JS_StopOutputPager, console)
|
||||
->GetFunction());
|
||||
|
||||
v8::Local<v8::Value> shell = v8::External::New(_isolate, this);
|
||||
TRI_AddGlobalVariableVocbase(
|
||||
_isolate, TRI_V8_ASCII_STRING(_isolate, "SYS_START_FLUX"),
|
||||
v8::FunctionTemplate::New(_isolate, JS_StartFlux, shell)
|
||||
->GetFunction());
|
||||
}
|
||||
|
||||
void V8ShellFeature::initMode(ShellFeature::RunMode runMode,
|
||||
|
|
|
@ -47,6 +47,10 @@ class V8ShellFeature final : public application_features::ApplicationFeature {
|
|||
void start() override final;
|
||||
void unprepare() override final;
|
||||
|
||||
std::string const& startupDirectory() {
|
||||
return _startupDirectory;
|
||||
}
|
||||
|
||||
private:
|
||||
std::string _startupDirectory;
|
||||
std::vector<std::string> _moduleDirectory;
|
||||
|
|
|
@ -461,6 +461,15 @@ global.DEFINE_MODULE('internal', (function () {
|
|||
delete global.SYS_CHECK_AND_MARK_NONCE;
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief input
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
if (global.SYS_POLLSTDIN) {
|
||||
exports.pollStdin = global.SYS_POLLSTDIN;
|
||||
delete global.SYS_POLLSTDIN;
|
||||
}
|
||||
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
// / @brief output
|
||||
// //////////////////////////////////////////////////////////////////////////////
|
||||
|
@ -1892,5 +1901,15 @@ global.DEFINE_MODULE('internal', (function () {
|
|||
delete global.SYS_IS_STOPPING;
|
||||
}
|
||||
|
||||
if (global.SYS_TERMINAL_SIZE) {
|
||||
exports.terminalSize = global.SYS_TERMINAL_SIZE;
|
||||
delete global.SYS_TERMINAL_SIZE;
|
||||
}
|
||||
|
||||
if (global.SYS_START_FLUX) {
|
||||
exports.startFlux = global.SYS_START_FLUX;
|
||||
delete global.SYS_START_FLUX;
|
||||
}
|
||||
|
||||
return exports;
|
||||
}()));
|
||||
|
|
|
@ -0,0 +1,421 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright (c) 2012 Nathan Rajlich <nathan@tootallnate.net>
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
|
||||
/**
|
||||
* References:
|
||||
*
|
||||
* - http://en.wikipedia.org/wiki/ANSI_escape_code
|
||||
* - http://www.termsys.demon.co.uk/vtansi.htm
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* Module dependencies.
|
||||
*/
|
||||
|
||||
var prefix = '\x1b[' // For all escape codes
|
||||
, suffix = 'm' // Only for color codes
|
||||
|
||||
/**
|
||||
* The ANSI escape sequences.
|
||||
*/
|
||||
|
||||
var codes = {
|
||||
up: 'A'
|
||||
, down: 'B'
|
||||
, forward: 'C'
|
||||
, back: 'D'
|
||||
, nextLine: 'E'
|
||||
, previousLine: 'F'
|
||||
, horizontalAbsolute: 'G'
|
||||
, eraseData: 'J'
|
||||
, eraseLine: 'K'
|
||||
, scrollUp: 'S'
|
||||
, scrollDown: 'T'
|
||||
, savePosition: 's'
|
||||
, restorePosition: 'u'
|
||||
, queryPosition: '6n'
|
||||
, hide: '?25l'
|
||||
, show: '?25h'
|
||||
}
|
||||
|
||||
/**
|
||||
* Rendering ANSI codes.
|
||||
*/
|
||||
|
||||
var styles = {
|
||||
bold: 1
|
||||
, italic: 3
|
||||
, underline: 4
|
||||
, inverse: 7
|
||||
}
|
||||
|
||||
/**
|
||||
* The negating ANSI code for the rendering modes.
|
||||
*/
|
||||
|
||||
var reset = {
|
||||
bold: 22
|
||||
, italic: 23
|
||||
, underline: 24
|
||||
, inverse: 27
|
||||
}
|
||||
|
||||
/**
|
||||
* The standard, styleable ANSI colors.
|
||||
*/
|
||||
|
||||
var colors = {
|
||||
white: 37
|
||||
, black: 30
|
||||
, blue: 34
|
||||
, cyan: 36
|
||||
, green: 32
|
||||
, magenta: 35
|
||||
, red: 31
|
||||
, yellow: 33
|
||||
, grey: 90
|
||||
, brightBlack: 90
|
||||
, brightRed: 91
|
||||
, brightGreen: 92
|
||||
, brightYellow: 93
|
||||
, brightBlue: 94
|
||||
, brightMagenta: 95
|
||||
, brightCyan: 96
|
||||
, brightWhite: 97
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a Cursor instance based off the given `writable stream` instance.
|
||||
*/
|
||||
|
||||
function ansi (stream, options) {
|
||||
if (stream._ansicursor) {
|
||||
return stream._ansicursor
|
||||
} else {
|
||||
return stream._ansicursor = new Cursor(stream, options)
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The `Cursor` class.
|
||||
*/
|
||||
|
||||
function Cursor (stream, options) {
|
||||
if (!(this instanceof Cursor)) {
|
||||
return new Cursor(stream, options)
|
||||
}
|
||||
if (typeof stream != 'object' || typeof stream.write != 'function') {
|
||||
throw new Error('a valid Stream instance must be passed in')
|
||||
}
|
||||
|
||||
// the stream to use
|
||||
this.stream = stream
|
||||
|
||||
// when 'enabled' is false then all the functions are no-ops except for write()
|
||||
this.enabled = options && options.enabled
|
||||
if (typeof this.enabled === 'undefined') {
|
||||
this.enabled = stream.isTTY
|
||||
}
|
||||
this.enabled = !!this.enabled
|
||||
|
||||
// then `buffering` is true, then `write()` calls are buffered in
|
||||
// memory until `flush()` is invoked
|
||||
this.buffering = !!(options && options.buffering)
|
||||
this._buffer = []
|
||||
|
||||
// controls the foreground and background colors
|
||||
this.fg = this.foreground = new Colorer(this, 0)
|
||||
this.bg = this.background = new Colorer(this, 10)
|
||||
|
||||
// defaults
|
||||
this.Bold = false
|
||||
this.Italic = false
|
||||
this.Underline = false
|
||||
this.Inverse = false
|
||||
|
||||
// keep track of the number of "newlines" that get encountered
|
||||
this.newlines = 0
|
||||
}
|
||||
exports.Cursor = Cursor
|
||||
|
||||
/**
|
||||
* Helper function that calls `write()` on the underlying Stream.
|
||||
* Returns `this` instead of the write() return value to keep
|
||||
* the chaining going.
|
||||
*/
|
||||
|
||||
Cursor.prototype.write = function (data) {
|
||||
if (this.buffering) {
|
||||
this._buffer.push(arguments)
|
||||
} else {
|
||||
this.stream.write.apply(this.stream, arguments)
|
||||
}
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer `write()` calls into memory.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Cursor.prototype.buffer = function () {
|
||||
this.buffering = true
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Write out the in-memory buffer.
|
||||
*
|
||||
* @api public
|
||||
*/
|
||||
|
||||
Cursor.prototype.flush = function () {
|
||||
this.buffering = false
|
||||
var str = this._buffer.map(function (args) {
|
||||
if (args.length != 1) throw new Error('unexpected args length! ' + args.length);
|
||||
return args[0];
|
||||
}).join('');
|
||||
this._buffer.splice(0); // empty
|
||||
this.write(str);
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* The `Colorer` class manages both the background and foreground colors.
|
||||
*/
|
||||
|
||||
function Colorer (cursor, base) {
|
||||
this.current = null
|
||||
this.cursor = cursor
|
||||
this.base = base
|
||||
}
|
||||
exports.Colorer = Colorer
|
||||
|
||||
/**
|
||||
* Write an ANSI color code, ensuring that the same code doesn't get rewritten.
|
||||
*/
|
||||
|
||||
Colorer.prototype._setColorCode = function setColorCode (code) {
|
||||
var c = String(code)
|
||||
if (this.current === c) return
|
||||
this.cursor.enabled && this.cursor.write(prefix + c + suffix)
|
||||
this.current = c
|
||||
return this
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Set up the positional ANSI codes.
|
||||
*/
|
||||
|
||||
Object.keys(codes).forEach(function (name) {
|
||||
var code = String(codes[name])
|
||||
Cursor.prototype[name] = function () {
|
||||
var c = code
|
||||
if (arguments.length > 0) {
|
||||
c = toArray(arguments).map(Math.round).join(';') + code
|
||||
}
|
||||
this.enabled && this.write(prefix + c)
|
||||
return this
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Set up the functions for the rendering ANSI codes.
|
||||
*/
|
||||
|
||||
Object.keys(styles).forEach(function (style) {
|
||||
var name = style[0].toUpperCase() + style.substring(1)
|
||||
, c = styles[style]
|
||||
, r = reset[style]
|
||||
|
||||
Cursor.prototype[style] = function () {
|
||||
if (this[name]) return this
|
||||
this.enabled && this.write(prefix + c + suffix)
|
||||
this[name] = true
|
||||
return this
|
||||
}
|
||||
|
||||
Cursor.prototype['reset' + name] = function () {
|
||||
if (!this[name]) return this
|
||||
this.enabled && this.write(prefix + r + suffix)
|
||||
this[name] = false
|
||||
return this
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Setup the functions for the standard colors.
|
||||
*/
|
||||
|
||||
Object.keys(colors).forEach(function (color) {
|
||||
var code = colors[color]
|
||||
|
||||
Colorer.prototype[color] = function () {
|
||||
this._setColorCode(this.base + code)
|
||||
return this.cursor
|
||||
}
|
||||
|
||||
Cursor.prototype[color] = function () {
|
||||
return this.foreground[color]()
|
||||
}
|
||||
})
|
||||
|
||||
/**
|
||||
* Makes a beep sound!
|
||||
*/
|
||||
|
||||
Cursor.prototype.beep = function () {
|
||||
this.enabled && this.write('\x07')
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Moves cursor to specific position
|
||||
*/
|
||||
|
||||
Cursor.prototype.goto = function (x, y) {
|
||||
x = x | 0
|
||||
y = y | 0
|
||||
this.enabled && this.write(prefix + y + ';' + x + 'H')
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the color.
|
||||
*/
|
||||
|
||||
Colorer.prototype.reset = function () {
|
||||
this._setColorCode(this.base + 39)
|
||||
return this.cursor
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets all ANSI formatting on the stream.
|
||||
*/
|
||||
|
||||
Cursor.prototype.reset = function () {
|
||||
this.enabled && this.write(prefix + '0' + suffix)
|
||||
this.Bold = false
|
||||
this.Italic = false
|
||||
this.Underline = false
|
||||
this.Inverse = false
|
||||
this.foreground.current = null
|
||||
this.background.current = null
|
||||
return this
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the foreground color with the given RGB values.
|
||||
* The closest match out of the 216 colors is picked.
|
||||
*/
|
||||
|
||||
Colorer.prototype.rgb = function (r, g, b) {
|
||||
var base = this.base + 38
|
||||
, code = rgb(r, g, b)
|
||||
this._setColorCode(base + ';5;' + code)
|
||||
return this.cursor
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `cursor.fg.rgb(r, g, b)`.
|
||||
*/
|
||||
|
||||
Cursor.prototype.rgb = function (r, g, b) {
|
||||
return this.foreground.rgb(r, g, b)
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts CSS color codes for use with ANSI escape codes.
|
||||
* For example: `#FF000` would be bright red.
|
||||
*/
|
||||
|
||||
Colorer.prototype.hex = function (color) {
|
||||
return this.rgb.apply(this, hex(color))
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as `cursor.fg.hex(color)`.
|
||||
*/
|
||||
|
||||
Cursor.prototype.hex = function (color) {
|
||||
return this.foreground.hex(color)
|
||||
}
|
||||
|
||||
|
||||
// UTIL FUNCTIONS //
|
||||
|
||||
/**
|
||||
* Translates a 255 RGB value to a 0-5 ANSI RGV value,
|
||||
* then returns the single ANSI color code to use.
|
||||
*/
|
||||
|
||||
function rgb (r, g, b) {
|
||||
var red = r / 255 * 5
|
||||
, green = g / 255 * 5
|
||||
, blue = b / 255 * 5
|
||||
return rgb5(red, green, blue)
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns rgb 0-5 values into a single ANSI color code to use.
|
||||
*/
|
||||
|
||||
function rgb5 (r, g, b) {
|
||||
var red = Math.round(r)
|
||||
, green = Math.round(g)
|
||||
, blue = Math.round(b)
|
||||
return 16 + (red*36) + (green*6) + blue
|
||||
}
|
||||
|
||||
/**
|
||||
* Accepts a hex CSS color code string (# is optional) and
|
||||
* translates it into an Array of 3 RGB 0-255 values, which
|
||||
* can then be used with rgb().
|
||||
*/
|
||||
|
||||
function hex (color) {
|
||||
var c = color[0] === '#' ? color.substring(1) : color
|
||||
, r = c.substring(0, 2)
|
||||
, g = c.substring(2, 4)
|
||||
, b = c.substring(4, 6)
|
||||
return [parseInt(r, 16), parseInt(g, 16), parseInt(b, 16)]
|
||||
}
|
||||
|
||||
/**
|
||||
* Turns an array-like object into a real array.
|
||||
*/
|
||||
|
||||
function toArray (a) {
|
||||
var i = 0
|
||||
, l = a.length
|
||||
, rtn = []
|
||||
for (; i<l; i++) {
|
||||
rtn.push(a[i])
|
||||
}
|
||||
return rtn
|
||||
}
|
||||
|
||||
module.exports = exports = ansi
|
|
@ -0,0 +1,234 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright (c) 2014 Alistair G MacDonald
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
(function() {
|
||||
|
||||
var internal = require('internal');
|
||||
//const Writable = require('stream').Writable;
|
||||
class StdoutWritable {//extends Writable
|
||||
constructor(options) {
|
||||
// Calls the stream.Writable() constructor
|
||||
//super(options);
|
||||
|
||||
this._type = 'tty';
|
||||
this.isTTY = internal.COLOR_OUTPUT;
|
||||
}
|
||||
|
||||
get rows() {
|
||||
var size = internal.terminalSize();
|
||||
return size[0];
|
||||
}
|
||||
|
||||
get columns() {
|
||||
var size = internal.terminalSize();
|
||||
return size[1];
|
||||
}
|
||||
|
||||
write(chunk, encoding, callback) {
|
||||
internal.output(chunk);
|
||||
if (callback) {callback();}
|
||||
}
|
||||
}
|
||||
|
||||
// Requires
|
||||
var ansi = require('./ansi')
|
||||
, stdo = new StdoutWritable()
|
||||
, cursor = ansi(stdo)
|
||||
, cols = stdo.columns
|
||||
, rows = stdo.rows
|
||||
, defaultChar = ' '
|
||||
|
||||
, PI2 = Math.PI*2
|
||||
|
||||
, color = {
|
||||
fg:{ r: 255, g: 255, b: 255 },
|
||||
bg:{ r: 255, g: 255, b: 255 }
|
||||
}
|
||||
;
|
||||
|
||||
|
||||
|
||||
var axel = {
|
||||
|
||||
// Clears a block
|
||||
scrub: function(x1, y1, w, h){
|
||||
|
||||
// Turn off the color settings while we scrub
|
||||
var oldBrush = this.defaultChar;
|
||||
cursor.reset();
|
||||
this.defaultChar = ' ';
|
||||
|
||||
this.box(x1, y1, w, h);
|
||||
|
||||
// Put the colors back after
|
||||
cursor.fg.rgb(color.fg.r, color.fg.g, color.fg.b);
|
||||
cursor.bg.rgb(color.bg.r, color.bg.g, color.bg.b);
|
||||
this.defaultChar = oldBrush;
|
||||
},
|
||||
|
||||
|
||||
clear:function () {
|
||||
console.log('\033[2J');
|
||||
},
|
||||
|
||||
|
||||
// Changes the foreground character █ default is [space]
|
||||
set brush (character){
|
||||
defaultChar = character || ' ';
|
||||
},
|
||||
|
||||
get brush (){
|
||||
return defaultChar;
|
||||
},
|
||||
|
||||
|
||||
cursorInterface: {
|
||||
on: function () { cursor.show(); },
|
||||
off: function () { cursor.hide(); },
|
||||
|
||||
// Resets background & foreground colors
|
||||
reset: function () { cursor.reset(); },
|
||||
|
||||
// Restores colors and places cursor after the graphics
|
||||
// so that the drawing does not get drawn over when the
|
||||
// program ends
|
||||
restore: function () {
|
||||
cursor.reset();
|
||||
cursor.goto(axel.cols, axel.rows-1);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
get cursor() {
|
||||
return this.cursorInterface;
|
||||
},
|
||||
|
||||
get rows (){
|
||||
return stdo.rows;
|
||||
},
|
||||
|
||||
get cols (){
|
||||
return stdo.columns;
|
||||
},
|
||||
|
||||
goto: function(x, y){
|
||||
cursor.goto(parseInt(x), parseInt(y));
|
||||
},
|
||||
|
||||
point: function (x, y, char){
|
||||
if(!(
|
||||
x < 0 || y < 0 ||
|
||||
x > stdo.columns || y > stdo.rows ||
|
||||
x < 0 || y < 0 ||
|
||||
x > stdo.columns || y > stdo.rows
|
||||
)){
|
||||
cursor.goto(parseInt(x), parseInt(y)).write(char || defaultChar);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Get in interpolation point between two points at a given magnitude
|
||||
lerp: function (p1, p2, m) {
|
||||
return ((p2 - p1) * m) + p1;
|
||||
},
|
||||
|
||||
|
||||
circ: function (x, y, m) {
|
||||
var res = m*PI2
|
||||
, i
|
||||
;
|
||||
|
||||
for(i=0; i< res; i+=1){
|
||||
var loc = PI2/res * i;
|
||||
this.point(x+Math.sin(loc)*m,y+Math.cos(loc)*m/2);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
box: function (x1, y1, w, h) {
|
||||
var line = ''
|
||||
, x
|
||||
, y
|
||||
;
|
||||
|
||||
for (x=0; x< w; x+=1) {
|
||||
line+=this.brush;
|
||||
}
|
||||
|
||||
for (y=0; y< h; y+=1) {
|
||||
cursor.goto(x1,y1+y).write(line);
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
// Get the distance between two points
|
||||
dist: function (x1, y1, x2, y2){
|
||||
return Math.sqrt(Math.pow(x2-x1,2) + Math.pow(y2-y1,2));
|
||||
},
|
||||
|
||||
|
||||
// Get all the points along a line and draw them
|
||||
line: function (x1, y1, x2, y2) {
|
||||
var D = this.dist(x1, y1, x2, y2)+1;
|
||||
|
||||
// this.point(x1, y1);
|
||||
for(var i=0; i< D; i++){
|
||||
var m = 1 / D * i
|
||||
, x = this.lerp(x1, x2, m)
|
||||
, y = this.lerp(y1, y2, m)
|
||||
;
|
||||
this.point(x, y);
|
||||
}
|
||||
// this.point(x2, y2);
|
||||
},
|
||||
|
||||
color: function (hex, g, b, a) {
|
||||
// if
|
||||
},
|
||||
|
||||
text: function(x, y, text){
|
||||
cursor.goto(x,y).write(text);
|
||||
},
|
||||
|
||||
|
||||
// moveTo: function (x, y) {
|
||||
// cursor.moveTo()
|
||||
// },
|
||||
|
||||
|
||||
// Changes foreground color
|
||||
fg: function (r, g, b) {
|
||||
cursor.fg.rgb(r,g,b);
|
||||
},
|
||||
|
||||
// Changes background color
|
||||
bg: function (r, g, b) {
|
||||
cursor.bg.rgb(r,g,b);
|
||||
},
|
||||
|
||||
draw: function(cb){
|
||||
with(this){
|
||||
cb();
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = axel;
|
||||
|
||||
}());
|
|
@ -0,0 +1,315 @@
|
|||
'use strict';
|
||||
|
||||
/**
|
||||
* @license
|
||||
* Copyright (c) 2014 Alistair G MacDonald
|
||||
*
|
||||
* (The MIT License)
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated
|
||||
* documentation files (the 'Software'), to deal in the Software without restriction, including without limitation the
|
||||
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit
|
||||
* persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT
|
||||
* NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
|
||||
* DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
//Requires
|
||||
var c = require('js/contrib/flux/axel')
|
||||
, internal = require('internal')
|
||||
, int = parseInt
|
||||
, sin = Math.sin
|
||||
// , cos = Math.cos
|
||||
// , floor = Math.floor
|
||||
// , ceil = Math.ceil
|
||||
// , pow = Math.pow
|
||||
, score = 0
|
||||
, bullets = []
|
||||
, maxBullets = 20
|
||||
, bulletSpeed = 0.425
|
||||
, width = c.cols
|
||||
, height = c.rows
|
||||
, p1x = c.cols/2
|
||||
, p1y = c.rows-2
|
||||
, lp1x = p1x
|
||||
, lp1y = p1y
|
||||
, interval = 20
|
||||
, isEnabled = true
|
||||
, tick =0
|
||||
, enemies = []
|
||||
, maxEnemies = 24
|
||||
, enemySpeed = 0.025
|
||||
;
|
||||
|
||||
// var theBrush = '█';
|
||||
var theBrush = ' ';
|
||||
|
||||
genEnemies();
|
||||
function genEnemies(){
|
||||
for (var y=0; y< c.rows; y+=3){
|
||||
for (var x=0; x< c.cols*0.75; x+=4){
|
||||
enemies.push({
|
||||
x: 2+x,
|
||||
y: y
|
||||
});
|
||||
if (enemies.length>=maxEnemies) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function shoot(){
|
||||
var newBullet = {
|
||||
x: p1x,
|
||||
y: p1y-3,
|
||||
speed: bulletSpeed
|
||||
};
|
||||
|
||||
bullets.push(newBullet);
|
||||
|
||||
if(bullets.length>maxBullets){
|
||||
bullets.shift();
|
||||
}
|
||||
}
|
||||
|
||||
function updateBullets(){
|
||||
bullets.forEach(function(bullet){
|
||||
|
||||
// Set last positions
|
||||
bullet.lx = bullet.x;
|
||||
bullet.ly = bullet.y;
|
||||
|
||||
// Move and accelarate
|
||||
bullet.y-=bullet.speed;
|
||||
bullet.speed+=bullet.speed*0.025;
|
||||
|
||||
|
||||
|
||||
if( int(bullet.x)!==int(bullet.lx) ||
|
||||
int(bullet.y)!==int(bullet.ly))
|
||||
{
|
||||
// Draw off
|
||||
c.cursor.reset();
|
||||
c.brush = ' ';
|
||||
c.point(bullet.lx, bullet.ly);
|
||||
|
||||
// Draw on
|
||||
c.brush = theBrush;
|
||||
c.bg(0,255,0);
|
||||
c.point(bullet.x, bullet.y);
|
||||
}
|
||||
|
||||
function destroyBullet(){
|
||||
c.cursor.reset();
|
||||
c.brush = ' ';
|
||||
c.point(bullet.x, bullet.y);
|
||||
bullets.shift();
|
||||
return;
|
||||
}
|
||||
|
||||
enemies.forEach(function(enemy,i){
|
||||
var D = c.dist(enemy.x, enemy.y, bullet.x, bullet.y);
|
||||
if(D<5){
|
||||
genExplosion(enemy.x,enemy.y);
|
||||
destroyBullet();
|
||||
enemies.splice(i,1);
|
||||
updateScore(12.34*bullet.speed);
|
||||
}
|
||||
});
|
||||
|
||||
if(bullet.y<1){
|
||||
destroyBullet();
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
var explosions = [];
|
||||
function genExplosion(x,y){
|
||||
explosions.push({
|
||||
x:x,
|
||||
y:y,
|
||||
size:0,
|
||||
lsize:0,
|
||||
rate: 1,
|
||||
max: 5
|
||||
});
|
||||
}
|
||||
function updateExplosions(){
|
||||
explosions.forEach(function(exp){
|
||||
exp.lsize = exp.size;
|
||||
|
||||
c.cursor.reset();
|
||||
c.brush = ' ';
|
||||
c.circ(exp.x, exp.y, exp.lsize);
|
||||
|
||||
c.bg(255,128,0);
|
||||
c.brush = theBrush;
|
||||
c.circ(exp.x, exp.y, exp.size);
|
||||
|
||||
exp.size+=exp.rate;
|
||||
if(exp.size>exp.max){
|
||||
c.cursor.reset();
|
||||
c.circ(exp.x, exp.y, exp.lsize);
|
||||
explosions.shift();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function updateEnemies(){
|
||||
enemies.forEach(function(enemy){
|
||||
enemy.ly = enemy.y;
|
||||
enemy.lx = enemy.x;
|
||||
enemy.y+=enemySpeed;
|
||||
enemy.x=enemy.x+(sin(tick/10)/1.5);
|
||||
|
||||
// Only draw enemies again if they have moved
|
||||
if(int(enemy.y)!==int(enemy.ly) ||
|
||||
int(enemy.x)!==int(enemy.lx))
|
||||
{
|
||||
c.cursor.reset();
|
||||
c.brush = ' ';
|
||||
drawEnemy(int(enemy.lx), int(enemy.ly));
|
||||
|
||||
c.bg(255,0,0);
|
||||
c.brush = theBrush;
|
||||
drawEnemy(int(enemy.x), int(enemy.y));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function updateScore(add){
|
||||
score+=add;
|
||||
c.cursor.reset();
|
||||
c.fg(255,255,255);
|
||||
c.text(0, c.rows, "Score: "+ int(score));
|
||||
}
|
||||
|
||||
function drawPlayer(x, y){
|
||||
c.brush = theBrush;
|
||||
c.bg(0,255,0);
|
||||
c.line(x-2, y, x+2, y);
|
||||
c.line(x, y, x, y-3);
|
||||
c.line(x-2, y, x-2, y-2);
|
||||
c.line(x+2, y, x+2, y-2);
|
||||
}
|
||||
|
||||
function erasePlayer(x, y){
|
||||
c.brush = ' ';
|
||||
c.cursor.reset();
|
||||
c.line(x-2, y, x+2, y);
|
||||
c.line(x, y, x, y-3);
|
||||
c.line(x-2, y, x-2, y-2);
|
||||
c.line(x+2, y, x+2, y-2);
|
||||
}
|
||||
|
||||
function drawEnemy(x,y){
|
||||
c.line(x-1, y, x+1, y);
|
||||
c.line(x-1, y, x-1, y+2);
|
||||
c.line(x+1, y, x+1, y+2);
|
||||
}
|
||||
|
||||
|
||||
function eachLoop(){
|
||||
tick+=1;
|
||||
|
||||
width = c.cols;
|
||||
height = c.rows;
|
||||
|
||||
pollKeyboard();
|
||||
|
||||
updateBullets();
|
||||
updateEnemies();
|
||||
updateExplosions();
|
||||
checkKeyDown();
|
||||
|
||||
erasePlayer(lp1x,lp1y);
|
||||
drawPlayer(p1x,p1y);
|
||||
}
|
||||
|
||||
|
||||
function endGame(){
|
||||
isEnabled = false;
|
||||
c.cursor.on();
|
||||
c.cursor.restore();
|
||||
internal.print(" Good Bye!");
|
||||
}
|
||||
|
||||
|
||||
function start(){
|
||||
c.cursor.off();
|
||||
c.clear();
|
||||
c.scrub(1, 1, c.cols, c.rows);
|
||||
while (isEnabled) {
|
||||
eachLoop();
|
||||
internal.sleep(1 / 45);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
start();
|
||||
|
||||
|
||||
function left(){
|
||||
lp1x = p1x;
|
||||
p1x-=p1x>4?1:0;
|
||||
}
|
||||
function right(){
|
||||
lp1x = p1x;
|
||||
p1x+=p1x<width-4?1:0;
|
||||
}
|
||||
|
||||
|
||||
//// KEYBOARD EVENTS ///////////////////////////////////////////////////////
|
||||
|
||||
|
||||
var keyDown = null;
|
||||
var lastChecked = now();
|
||||
var releaseTime = 25;
|
||||
|
||||
function now(){
|
||||
return (+new Date());
|
||||
};
|
||||
|
||||
|
||||
var dir;
|
||||
function checkKeyDown(){
|
||||
// if (now()-lastChecked>30){
|
||||
// keyDown =null;
|
||||
// }
|
||||
|
||||
switch(dir){
|
||||
case 'left':
|
||||
left();
|
||||
break;
|
||||
case 'right':
|
||||
right();
|
||||
break;
|
||||
}
|
||||
|
||||
lastChecked = now();
|
||||
}
|
||||
|
||||
function pollKeyboard() {
|
||||
var code = internal.pollStdin();
|
||||
|
||||
if (code) {
|
||||
if (code == 27) endGame();// esc
|
||||
if (code == 3) endGame();// esc
|
||||
if (code == 113 || code == 81) endGame();// q
|
||||
if (code == 97 || code == 65 || code == 37) dir = 'left';// a
|
||||
if (code == 100 || code == 68 || code == 39) dir = 'right';// d
|
||||
if (code == 32 || code == 119 || code == 38) shoot();// w / space
|
||||
}
|
||||
}
|
|
@ -31,14 +31,15 @@
|
|||
/// @brief returns the columns width
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ColumnsWidth() {
|
||||
TRI_TerminalSize TRI_DefaultTerminalSize() {
|
||||
unsigned short values[4];
|
||||
|
||||
|
||||
int ret;
|
||||
|
||||
ret = ioctl(0, TIOCGWINSZ, &values);
|
||||
|
||||
return ret == -1 ? TRI_DEFAULT_COLUMNS : values[1];
|
||||
if (ret == -1) {
|
||||
return TRI_DEFAULT_TERMINAL_SIZE;
|
||||
}
|
||||
return TRI_TerminalSize{values[0], values[1]};
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -29,19 +29,19 @@
|
|||
/// @brief returns the columns width
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ColumnsWidth() {
|
||||
TRI_TerminalSize TRI_DefaultTerminalSize() {
|
||||
HANDLE hOut;
|
||||
CONSOLE_SCREEN_BUFFER_INFO SBInfo;
|
||||
|
||||
hOut = GetStdHandle(STD_OUTPUT_HANDLE);
|
||||
|
||||
if (hOut == INVALID_HANDLE_VALUE) {
|
||||
return TRI_DEFAULT_COLUMNS;
|
||||
return TRI_DEFAULT_TERMINAL_SIZE;
|
||||
}
|
||||
|
||||
if (GetConsoleScreenBufferInfo(hOut, &SBInfo) == 0) {
|
||||
return TRI_DEFAULT_COLUMNS;
|
||||
return TRI_DEFAULT_TERMINAL_SIZE;
|
||||
}
|
||||
|
||||
return SBInfo.dwSize.X;
|
||||
return TRI_TerminalSize{SBInfo.dwSize.Y, SBInfo.dwSize.X};
|
||||
}
|
||||
|
|
|
@ -29,20 +29,30 @@
|
|||
|
||||
#if !defined(TRI_HAVE_SYS_IOCTL_H) && !defined(TRI_WIN32_CONSOLE)
|
||||
|
||||
int TRI_ColumnsWidth(void) {
|
||||
TRI_TerminalSize TRI_DefaultTerminalSize() {
|
||||
char* e = getenv("COLUMNS");
|
||||
|
||||
int colums;
|
||||
if (e != 0) {
|
||||
int c = (int)TRI_Int32String(e);
|
||||
colums = (int)TRI_Int32String(e);
|
||||
|
||||
if (c == 0 || TRI_errno() != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_DEFAULT_COLUMNS;
|
||||
if (colums == 0 || TRI_errno() != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_DEFAULT_TERMINAL_SIZE;
|
||||
}
|
||||
|
||||
e = getenv("LINES");
|
||||
int rows;
|
||||
if (e != 0) {
|
||||
rows = (int)TRI_Int32String(e);
|
||||
|
||||
if (rows == 0 || TRI_errno() != TRI_ERROR_NO_ERROR) {
|
||||
return TRI_DEFAULT_TERM_SIZE;
|
||||
}
|
||||
return TRI_TerminalSize{rows, columns};
|
||||
}
|
||||
|
||||
return c;
|
||||
}
|
||||
|
||||
return TRI_DEFAULT_COLUMNS;
|
||||
|
||||
return TRI_DEFAULT_TERMINAL_SIZE;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
|
|
@ -30,17 +30,22 @@
|
|||
#include <termios.h>
|
||||
#endif
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief default value for number of columns of a terminal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
#define TRI_DEFAULT_COLUMNS (80)
|
||||
struct TRI_TerminalSize {
|
||||
int rows;
|
||||
int columns;
|
||||
};
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the columns width
|
||||
/// @brief default value for number of rows/columns of a terminal
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
int TRI_ColumnsWidth(void);
|
||||
#define TRI_DEFAULT_TERMINAL_SIZE (TRI_TerminalSize{80, 80})
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns the terminal size
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
TRI_TerminalSize TRI_DefaultTerminalSize(void);
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief set the visibility of stdin inputs (turn off for password entry etc.)
|
||||
|
|
|
@ -43,7 +43,6 @@ ProgramOptions::ProgramOptions(char const* progname, std::string const& usage,
|
|||
: _progname(progname),
|
||||
_usage(usage),
|
||||
_more(more),
|
||||
_terminalWidth(TRI_ColumnsWidth),
|
||||
_similarity(TRI_Levenshtein),
|
||||
_processingResult(),
|
||||
_sealed(false),
|
||||
|
@ -78,7 +77,8 @@ void ProgramOptions::printHelp(std::string const& search) const {
|
|||
bool const colors = (isatty(STDOUT_FILENO) != 0);
|
||||
printUsage();
|
||||
|
||||
size_t const tw = _terminalWidth();
|
||||
TRI_TerminalSize ts = TRI_DefaultTerminalSize();
|
||||
size_t const tw = ts.columns;
|
||||
size_t const ow = optionsWidth();
|
||||
|
||||
for (auto const& it : _sections) {
|
||||
|
|
|
@ -83,9 +83,6 @@ class ProgramOptions {
|
|||
bool _failed;
|
||||
};
|
||||
|
||||
// function type for determining terminal width
|
||||
typedef std::function<size_t()> TerminalWidthFuncType;
|
||||
|
||||
// function type for determining the similarity between two strings
|
||||
typedef std::function<int(std::string const&, std::string const&)>
|
||||
SimilarityFuncType;
|
||||
|
@ -276,8 +273,6 @@ class ProgramOptions {
|
|||
// map with old options and their new equivalents, used for printing more
|
||||
// meaningful error messages when an invalid (but once valid) option was used
|
||||
std::unordered_map<std::string, std::string> _oldOptions;
|
||||
// callback function for determining the terminal width
|
||||
TerminalWidthFuncType _terminalWidth;
|
||||
// callback function for determining the similarity between two option names
|
||||
SimilarityFuncType _similarity;
|
||||
// option processing result
|
||||
|
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#ifdef _WIN32
|
||||
#include "Basics/win-utils.h"
|
||||
#include <conio.h>
|
||||
#endif
|
||||
|
||||
#include <signal.h>
|
||||
|
@ -46,6 +47,7 @@
|
|||
#include "Basics/Utf8Helper.h"
|
||||
#include "Basics/files.h"
|
||||
#include "Basics/process-utils.h"
|
||||
#include "Basics/terminal-utils.h"
|
||||
#include "Basics/tri-strings.h"
|
||||
#include "Basics/tri-zip.h"
|
||||
#include "Logger/Logger.h"
|
||||
|
@ -2277,6 +2279,53 @@ static void JS_CopyFile(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief reads from stdin
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void JS_PollStdin(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
if (args.Length() > 1) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("pollStdin()");
|
||||
}
|
||||
|
||||
bool hasData = false;
|
||||
#ifdef _WIN32
|
||||
hasData = _kbhit() != 0;
|
||||
#else
|
||||
struct timeval tv;
|
||||
fd_set fds;
|
||||
tv.tv_sec = 0;
|
||||
tv.tv_usec = 0;
|
||||
FD_ZERO(&fds);
|
||||
FD_SET(STDIN_FILENO, &fds);
|
||||
select(STDIN_FILENO+1, &fds, NULL, NULL, &tv);
|
||||
hasData = FD_ISSET(STDIN_FILENO, &fds);
|
||||
#endif
|
||||
|
||||
char c[3] = {0};
|
||||
if (hasData) {
|
||||
ssize_t n = TRI_READ(STDIN_FILENO, c, 3);
|
||||
if (n == 3) {// arrow keys are garbled
|
||||
if (c[2] == 'D') {
|
||||
TRI_V8_RETURN(v8::Integer::New(isolate, 37));
|
||||
}
|
||||
if (c[2] == 'A') {
|
||||
TRI_V8_RETURN(v8::Integer::New(isolate, 38));
|
||||
}
|
||||
if (c[2] == 'C') {
|
||||
TRI_V8_RETURN(v8::Integer::New(isolate, 39));
|
||||
}
|
||||
} else if (n == 1) {
|
||||
TRI_V8_RETURN(v8::Integer::New(isolate, c[0]));
|
||||
}
|
||||
}
|
||||
TRI_V8_RETURN(v8::Integer::New(isolate, 0));
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief outputs the arguments
|
||||
///
|
||||
|
@ -3890,6 +3939,28 @@ static void JS_IsStopping(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
|||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
/// @brief returns keycode of currently pressed key
|
||||
////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
static void JS_termsize(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
v8::HandleScope scope(isolate);
|
||||
|
||||
// extract the arguments
|
||||
if (args.Length() != 0) {
|
||||
TRI_V8_THROW_EXCEPTION_USAGE("termsize()");
|
||||
}
|
||||
|
||||
TRI_TerminalSize s = TRI_DefaultTerminalSize();
|
||||
v8::Handle<v8::Array> list = v8::Array::New(isolate, 2);
|
||||
list->Set(0, v8::Integer::New(isolate, s.rows));
|
||||
list->Set(1, v8::Integer::New(isolate, s.columns));
|
||||
|
||||
TRI_V8_RETURN(list);
|
||||
TRI_V8_TRY_CATCH_END
|
||||
}
|
||||
|
||||
/// @brief convert a V8 value to VPack
|
||||
static void JS_V8ToVPack(v8::FunctionCallbackInfo<v8::Value> const& args) {
|
||||
TRI_V8_TRY_CATCH_BEGIN(isolate);
|
||||
|
@ -4692,6 +4763,8 @@ void TRI_InitV8Utils(v8::Isolate* isolate, v8::Handle<v8::Context> context,
|
|||
TRI_V8_ASCII_STRING(isolate, "SYS_OPTIONS"), JS_Options);
|
||||
TRI_AddGlobalFunctionVocbase(isolate,
|
||||
TRI_V8_ASCII_STRING(isolate, "SYS_OUTPUT"), JS_Output);
|
||||
TRI_AddGlobalFunctionVocbase(isolate,
|
||||
TRI_V8_ASCII_STRING(isolate, "SYS_POLLSTDIN"), JS_PollStdin);
|
||||
TRI_AddGlobalFunctionVocbase(isolate,
|
||||
TRI_V8_ASCII_STRING(isolate, "SYS_PARSE"), JS_Parse);
|
||||
TRI_AddGlobalFunctionVocbase(
|
||||
|
@ -4739,9 +4812,10 @@ void TRI_InitV8Utils(v8::Isolate* isolate, v8::Handle<v8::Context> context,
|
|||
TRI_AddGlobalFunctionVocbase(isolate,
|
||||
TRI_V8_ASCII_STRING(isolate, "SYS_DEBUG_CAN_USE_FAILAT"),
|
||||
JS_DebugCanUseFailAt);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(
|
||||
isolate, TRI_V8_ASCII_STRING(isolate, "SYS_IS_STOPPING"), JS_IsStopping);
|
||||
TRI_AddGlobalFunctionVocbase(isolate,
|
||||
TRI_V8_ASCII_STRING(isolate, "SYS_TERMINAL_SIZE"), JS_termsize);
|
||||
|
||||
TRI_AddGlobalFunctionVocbase(
|
||||
isolate, TRI_V8_ASCII_STRING(isolate, "V8_TO_VPACK"), JS_V8ToVPack);
|
||||
|
|
Loading…
Reference in New Issue