How do I redirect stdout in blessed? - node.js

Long story short: I want to build a CLI for a development daemon. Daemon outputs different kind of information to stdout and I want to relay that information to user in an area of screen, in scrollable fashion.
I am struggling with getting stdout to blessed. Simple prototype below, which buffers stdout, so information is never complete.
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 1,
left: 0,
width: '100%',
height: '99%'
}),
statusbar = blessed.box({
top: 0,
left: 0,
width: '100%',
height: 1,
style: {
fg: 'white',
bg: 'blue'
}
});
screen.append(statusbar);
screen.append(body);
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
function status(text) { statusbar.setContent(text); screen.render(); }
function log(text) { body.insertLine(0, text); screen.render(); }
status('TEST');
var spawn = require('child_process').spawn;
yes = spawn('yes', ['it is']);
ls.stdout.on('data', function (data) {
log(data.toString());
});
ls.stderr.on('data', function (data) {
log(data.toString());
});

The line
var screen = blessed.screen()
Takes parameters in order to change where the input comes from, and where the output goes too. Logically, they're named input and output:
var screen = blessed.screen({ input: some_input_stream, output: some_output_stream })
So, you just chuck a writeable (or duplex) stream into the output parameter. Then, you can pipe the output anywhere you wish.

Related

Phaser 3: Spritesheet doesn't load correctly

I tried to add a spritesheet to my Phaser game the same way I've done it a few times before, however this time it seems to not load the images correctly, causing it to display a black & green square instead and causing it to throw an error when trying to play an animation.
Can anyone tell what is causing this issue?
(Warning: Playing the Code here seems to freeze up your browser for a few seconds, alternatively view on JSFiddle: https://jsfiddle.net/cak3goru/4/ )
// Configs and Constants
const gameState = {
gameWidth: 800,
gameHeight: 800,
textStyle: {
fontFamily: "'Comic Sans MS'",
fill: "#fff",
align: "center",
boundsAlignH: "left",
boundsAlignV: "top"
},
mouseDown: false,
menu: {
options: [
"Feed", "Clean", "Play"
],
barColor: "0x123456",
items: [],
itemText: [],
itemColor: "0x654321",
}
};
function preload() {
// Clean Tools
this.load.atlas('clean', 'https://gaylie.neocities.org/game/assets/clean.png', 'https://gaylie.neocities.org/game/assets/clean.json');
}
function create () {
this.anims.create({
key: "shower_cursor",
framerate: 12,
frames: this.anims.generateFrameNumbers("clean", {
prefix: "showerhead_000",
start: 0,
end: 7}),
repeat: -1
});
gameState.shower_cursor = this.add.sprite(400,400,'shower_cursor');
console.log(gameState.shower_cursor.frame);
//gameState.shower_cursor.playAfterDelay('shower_cursor', 100);
//gameState.shower_cursor.alpha = 0;
}
var config = {
backgroundColor: "0xf0f0f0",
scale: {
width: gameState.gameWidth,
height: gameState.gameHeight,
autoCenter: Phaser.Scale.CENTER_BOTH
},
scene: {
preload, create
}
};
var game = new Phaser.Game(config);
<head>
<title>Pet Simulator</title>
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.min.js"></script>
</head>
<body style="height: 100%; width: 100%; margin: 0;">
</body>
The problem is, that you are using the wrong function, you should use this.anims.generateFrameNames, and not this.anims.generateFrameNumbers.
And set the correct key clean for the sprite.
the line should be:
gameState.shower_cursor = this.add.sprite(200, 100, 'clean');
because shower_cursor, is only the key of the animation, not the key of the sprite.
P.s.: the posted code doesn't run on jsfiddler or Stackoverflow due to CORS-Error, but if all assets are on the same server, it should not be a problem.

How to make a tooltip appear when hovering mouse over a Phaser.GameObject.Image?

In my Phaser 3 game I'm using Phaser.GameObjects.Image 's as things that a user can click on. When a user's mouse hovers over an image I would like a tooltip with text to fade in and appear. When the mouse moves off the image, I'd like the tooltip to disappear.
How can I implement this behavior in Phaser? I'm new to Phaser and I don't see a ToolTip class in the framework.
You could:
use the pointer events for detecting, that the pointer is over an object
and animate/tween the alpha property on the over event
you can alter the speed with the tween duration
and hide the toolTip on the out event
Here the docs to the Input events: https://photonstorm.github.io/phaser3-docs/Phaser.Input.Events.html
Here a mini example:
var config = {
type: Phaser.WEBGL,
parent: 'phaser-example',
width: 800,
height: 600,
scene: {
create: create
}
};
var game = new Phaser.Game(config);
var toolTip;
var toolTipText;
function create ()
{
let objectWithToolTip = this.add.rectangle( 100, 100, 100, 100, 0xffffff).setInteractive();
toolTip = this.add.rectangle( 0, 0, 250, 50, 0xff0000).setOrigin(0);
toolTipText = this.add.text( 0, 0, 'This is a white rectangle', { fontFamily: 'Arial', color: '#000' }).setOrigin(0);
toolTip.alpha = 0;
this.input.setPollOnMove();
this.input.on('gameobjectover', function (pointer, gameObject) {
this.tweens.add({
targets: [toolTip, toolTipText],
alpha: {from:0, to:1},
repeat: 0,
duration: 500
});
}, this);
this.input.on('gameobjectout', function (pointer, gameObject) {
toolTip.alpha = 0;
toolTipText.alpha = 0;
});
objectWithToolTip.on('pointermove', function (pointer) {
toolTip.x = pointer.x;
toolTip.y = pointer.y;
toolTipText.x = pointer.x + 5;
toolTipText.y = pointer.y + 5;
});
}
<script src="//cdn.jsdelivr.net/npm/phaser#3.55.2/dist/phaser.min.js"></script>
Info: if you want to dig deeper into the phaser events you can checkout some examples on the offical home page: https://phaser.io/examples/v3/category/input/mouse are really good, and explore may use cases.
Extra Info: If you don't want to re-invent the wheel, there are several plugins, that can be loaded into phaser(that add special functionality to phaser).
It is always good to check this page(https://phaserplugins.com/), before implementing so common feature/function. There is even on specially for tooltips https://github.com/netgfx/Phaser-tooltip

How to clear screen using node/npm blessed (curses-like library)

I am using node/npm blessed to create a screen to monitor a particular application and I want the monitor tool to look/act like linux top. The problem I have, which I think is relatively simple (but I cant find the answer anywhere), is to have blessed clear the screen at startup as well as at particular points based upon user input.
Right now I can use blessed to paint the screen properly (sample program below), but the problem is I need the screen to be cleared at startup (right now the first line of output just appends right after you start up the program):
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 0,
left: 0,
width: '100%',
height: '100%',
tags: true
});
var items = [];
screen.append(body);
screen.key(['escape', 'q', 'C-c'], function(ch, key) {
return process.exit(0);
});
function log(text) {
items.push(text);
var MAX = 10;
if( items.length > MAX+1 ){
items.shift();
}
for (var i=1; i<MAX; i++){
body.setLine(i, items[i]);
}
screen.render();
}
function status(text) {
body.setLine(0, text );
screen.render();
}
var counter = 1;
setInterval(function() {
status((new Date()).toISOString());
log('Line number: ' + (counter++));
}, 1000);
For completeness, the solution to this question is provided below, and is very simple. To clear the screen, issue the following code at the start of the program:
screen.render();
The sample program that I referenced in the original post can be modified as follows and now works:
var blessed = require('blessed');
var screen = blessed.screen(),
body = blessed.box({
top: 0,
left: 0,
width: '100%',
height: '100%',
tags: true
});
// The following line clears the screen
screen.render();
:
:

What can I get a handle on the target of a fabric js event?

In this fabricjs tutorial section it says putting listeners right on an object like so
var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });
rect.on('selected', function() {
console.log('selected a rectangle');
});
That is fine, but I don't want to log a string to the console. I want to manipulate the rectangle. Specifically the rectangle isn't selectable by default and based on application state, I need to make it selectable.
I can't figure out how to get a handle on the rectangle from inside the event handler. How to do that escapes me.
In the example you gave, you have attached the event to the object itself. So you can access the object using this or the variable name (which is rect in your case). Here is an example
var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });
rect.on('selected', function() {
console.log(this);
this.set({width:200});
});
Alternatively, if you attach it to the canvas so that it listens to all the object:selected events, you can access the object at which the event occurred like this:
var rect = new fabric.Rect({ width: 100, height: 50, fill: 'green' });
canvas.on('object:selected', function (e) {
console.log('selected a rectangle');
e.target.set({width:200});
});

Render page element with padding in Poltergeist

I would like take screenshot of element with page context, let say 10px around element.
In PhantomJs I would do it
phantom.clipRect = { top: 14, left: 3, width: 400, height: 300 };
phantom.render(output);
I did not find clipRect in Poltergeist.
Is it possible to use phantom.clipRect?
Thanks
I found workaround, to make screenshot of element with 10px around element.
I add dynamically new DOM element 'wrap' and put it around target.
Then I take screenshot of wrap. It work!
Code:
result_file = File.expand_path('../tmp/screenshot.jpg', __FILE__)
browser.execute_script %Q(
// add jQuery
(function(){
function getScript(src, callback) {
var fileref = document.createElement('script');
fileref.setAttribute("type","text/javascript");
fileref.setAttribute("src", src);
if (callback) {
fileref.setAttribute("onload", callback());
}
document.getElementsByTagName("head")[0].appendChild(fileref);
}
getScript('https://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js', function(){
$(function() {
var target = $('#{screenshot_target_selector}');
var offset = target.offset();
var wrap = $('<div id="inlinemanual_screenshot_target_selector_wrap"></div>').prependTo('body');
wrap.css({
position: 'absolute',
width: target.outerWidth() + 20,
height: target.outerHeight() + 20,
top: offset.top - 10,
left: offset.left - 10
});
});
});
}())
)
browser.screenshot_element(result_file, '#inlinemanual_screenshot_target_selector_wrap')

Resources