1
0
Fork 0

terminal codes

This commit is contained in:
Frank Celler 2017-09-28 22:23:54 +02:00 committed by GitHub
parent 58515b7894
commit 70e206fc25
15 changed files with 1164 additions and 43 deletions

View File

@ -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

View File

@ -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

View File

@ -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,

View File

@ -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;

View File

@ -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;
}()));

421
js/contrib/flux/ansi.js Normal file
View File

@ -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

234
js/contrib/flux/axel.js Executable file
View File

@ -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;
}());

315
js/contrib/flux/flux.js Executable file
View File

@ -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
}
}

View File

@ -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

View File

@ -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};
}

View File

@ -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

View File

@ -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.)

View File

@ -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) {

View File

@ -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

View File

@ -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);