When working with the Node REPL console, I'm looking for a way for asynchronous calls to both not lock up the console input, and not clobber the console prompt when they return.
I've seen a few solutions dealing with asynchronous calls in the REPL, where writing your own custom eval function you can check the result of the executed code to see if it's a promise/async object, and just not return until it resolves.
However, I'd like to solve the issue of a repeating background process logging its progress. Ideally I'd like it to behave like the Chrome Javascript console, where if you have a command partially printed on the console prompt, and an async result gets logged, the line you're typing on gets moved one line down, and the log inserted above it.
So, functionally, I'd like to insert the logic that when console.log() is called, the line containing the cursor is first cleared, then the contents of the log() written, and then the REPL prompt (and whatever the user had typed so far onto it) gets re-written on the line following the new output.
Is there any way to hook into the REPL object to accomplish this? Is this some advanced manipulation of the output stream from the REPL (i.e. only possible on terminals that support an "erase to beginning of line" escape code)?
Tapping straight into the Output Stream I managed to get something working like how I wanted:
var server = repl.start({
prompt: '> '
});
server.context.console.log = function(msg) {
var rli = server.rli;
server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
server.outputStream.write(msg+"\n");
server.outputStream.write(''+rli._prompt+rli.line); // Redraw existing line
server.outputStream.write('\033['+(rli.cursor+rli._promptLength+1)+'G'); // Move the cursor to where it was
}
server.context.doTimeout = function() {
setTimeout(function() {
server.context.console.log('Timeout done!');
}, 2000);
};
Though that all assumes an ANSI-compliant output stream is the output, and feels quite hack-ish, overriding the console.log() function like that. Is there a more compliant way to handle this, or is this the best way?
Still, now I cannot find a modern satisfactory answer on StackOverflow.
After spending a few hours on the internet, I came up with this solution for latest Node (v15.*)
const log = (msg) => {
rl.output.write('\r')
rl.output.write(msg + '\n')
rl.displayPrompt(true)
}
Basically, clear the line, write the log, then display the prompt again. Works perfectly for my case.
Improved solution.
The above works well if the buffered line is not longer than the log. So here is another version that pad the rest of log by space characters
const log = (msg) => {
rl.output.write('\r');
rl.output.write(_.padEnd(msg, process.stdout.columns - 2, ' ') + '\n');
rl.displayPrompt(true);
};
_.padEnd: lodash's padEnd, can be replaced by any lib
Based on #MidnightLightning's older answer.
As of sometime before node v12.15.0 the console.log override would look like:
activeRepl.context.console.log = (msg) => {
const promptOffset = Server._prompt.length + Server.line.length;
Server.outputStream.write('\033[2K\033[1G'); // Erase to beginning of line, and reposition cursor at beginning of line
Server.outputStream.write(msg + "\n");
Server.outputStream.write('' + Server._prompt + Server.line); // Redraw existing line
Server.outputStream.write('\033[' + (promptOffset + 1) + 'G'); // Move the cursor to where it was
};
Related
i tried to find word api for that but i guess that is not available
right now so i thought i can do it by modifying the xml but that
also didn't work, need to change page size margin and document
language
await Word.run(async (context) => {
var paragraphs = context.document.body;
// Queue a command to load the style property for the top 2 paragraphs.
paragraphs.load("style")
// Synchronize the document state by executing the queued commands,
// and return a promise to indicate task completion.
return context.sync().then(function () {
// let replacedXml=""
// Queue a a set of commands to get the OOXML of the first paragraph.
var ooxml = paragraphs.getOoxml()
// Synchronize the document state by executing the queued commands,
// and return a promise to indicate task completion.
return context.sync().then(function () {
// console.log('Paragraph OOXML: ' + ooxml.value);
console.log(ooxml.value)
let str=String(ooxml.value)
let replacedXml =ooxml.value
// paragraphs.items[0].insertOoxml(replacedXml,Word.InsertLocation.replace)
// context.document.body.insertOoxml(replacedXml, Word.InsertLocation.replace);
var range = context.document.getSelection()
range.insertOoxml(replacedXml,"Replace")
// console.log(replacedXml)
});
});
i tried to find word api for that but i guess that is not available right now
The answer is yes. Here is no such api having functionality as your expectation for now and in recent future.
so i thought i can do it by modifying the xml but that also didn't work, need to change page size margin and document
OOxml is a powerful way to change doc file indeed, but it is only applicable for those very experienced, has a bit unsatisfying performance online and may cause some problems hard to interpret. So in most cases, we don't recommend using ooxml to achieve one's goal actually.
Btw, we suggest to test above code in word desktop app. Only if insuring the correctness of code could support us to go on investigating.
At last, you can submit your request in https://techcommunity.microsoft.com/t5/microsoft-365-developer-platform/idb-p/Microsoft365DeveloperPlatform if you really want new api.
I have a windbg-issue concerning the execution
of a javascript-function as a breakpoint-command.
This observation was made in windbg Preview 10.0.17030.1002
and also in recent versions of windbg
when debugging a native x86 C++ program on Windows 10.
Test Setup
In my javascript-file dbg_test.js I have the following function:
function test()
{
var ctl = host.namespace.Debugger.Utility.Control;
host.diagnostics.debugLog(">>> Test\n");
ctl.ExecuteCommand("g");
}
In windbg, I load the javascript-provider, load my dbg_test.js script
and define a breakpoint-command to call this javascript-function:
bs 0 "dx #$scriptContents.test()"
Expected Behavior
The string ">>> Test" is shown in the output-pane of the command-window
everytime when breakpoint 0 is hit.
The debugger resumes execution.
Observed Behavior
The output ">>> Test" is shown only the first time
when breakpoint 0 is hit.
Subsequently hitting breakpoint 0 does not
produce any output.
Remarks
1) Doing the analogous test with "old style" windbg-commands works fine:
bs 0 ".printf \">>> Test\\n\\n\";g;"
but only after ending and restarting windbg
2) The same behavior is shown when I move the code of function "test" to the function "invokeScript()" and define the breakpoint-command via
bs 0 ".scriptrun d:\\dbg_scripts\\dbg_test.js"
3) Running the script from the windbg-command-line works.
4) Calling javascript-functions as in the test-scenario above worked in previous versions of windbg.
5) It seems that the statement
ctl.ExecuteCommand("g");
is the crucial one: If I comment out this statement, then the breakpoint
is hit every time and the output from
host.diagnostics.debugLog(">>> Test\n");
is shown on each hit of the breakpoint.
Of course, I have to resume the execution manually by pressing F5 or entering the command "g"
Questions
Can someone reproduce this issue ?
Is it legal to use javascript-functions in this way or am I doing something wrong here ?
Your feedback is greatly appreciated!
Kind/Best regards!
I ran into the same problem as you did. I was able to somewhat bypass the problem by declaring a script global variable
var lines = [];
and pushing log messages to this array rather than debug printing them:
lines.push(">>> Test");
In order to see the lines, I created a function
function print_lines() {
for (var line of lines) {
host.diagnostics.debugLog(line + "\n");
}
lines = [];
}
which I called from the prompt like so
dx #$scriptContents.print_lines();
I know that this is not really answering your question, but it might still be helpful for someone else that faces the same problem.
Here this is, my weirdest error in my whole programming career. I've been struggling through this, yet I can't find what's going on in this code. It just seems not to make any sense in any way.
I'm using the following tools:
Ionic 3
Angular 4
Typescript / ES6
I'm trying to do a method, "assignChat(user)", which assigns a chat to a user. It has to use several APIs, geolocation... it's a big method, actually. That's why I've split it in two parts connected by promises, and used them after, so my method looks pretty much like this:
assignChat(user){
const getLocationName = () => {
return new Promise((resolve,reject) => {
// 30 lines of code
});
}
const assignOrCreateChat= (area) => {
return new Promise((resolve,reject) => {
// 40 lines of code
});
}
const getLocationName = () => {
return new Promise((resolve,reject) => {
// 30 lines of code
});
}
// then I use the inner functions here and write an extra 60-70 lines of code
}
Ok! This works neat. Didn't have much problems with this algorithm after some several testing, although is quite heavy and takes ~0.5s to properly execute, finish it's queries, and show the result.
Thing is... I had some toasts displaying some information, like where you're located. I wanted to remove them, and started by this one, in the inner function getLocationName(). This is the code I want to talk you about:
const getLocationName = () => {
return new Promise( (resolve, reject) => {
const ADDRESS_LEVEL = 2;
this.reverseGeocode(ADDRESS_LEVEL).then( address => {
---> this.toastify("You have been located at: "+address, 1500);
let query = new Parse.Query("PoliticalArea");
// more code
The line I marked with an arrow, is the line which is giving me problems. I mean, you probably think the code fails because of the line, but it's totally the oposite! If I remove that line, the algorithm suddenly stops working and fails to display any result.
The "toastify" method is a quick way I did for myself for displaying toasts. It works well, actually! This is the implementation:
toastify(message, duration){
this.toastCtrl.create({
message: message,
duration: duration
}).present();
}
Not like the most dangerous method. Well, in fact, it seems that the code won't work without it. If I comment the line, or erase it, I never get any result, or any error, from the big algorithm I showed you before. I've got every possible exception catched, although the API connectors don't have timeout, but it's like it gets stuck every time it doesn't display the toast.
I just don't understand what's going on. Seems like a very serious thing the Angular team should look into, in my very honest opinion.
Any idea of what kind of black magic is going there?
UPDATE:
Some further info: when I navigate through the "bugged" view (without the toastify line, and therefore not displaying the chat result), and per example, click in another chat (which pushes a view into the Navigation Controller), it somehow starts showing the chat result I expected. When I pop the new view from the navCtrl, and get back to the page, the expected result is now visible.
Is this some problem with angular watches?
Ok, the solution was not obvious.
It seems that the view was being rendered before the task completed. It was a tough task, so maybe that's the reason why Angular didn't work properly. Tried executing it both in the constructor and in ionViewDidEnter(), though nothing worked.
My final solution was to force component's re-rendering, through ApplicationRef, using the .tick() method at the dead end of my method.
That fixed it all!
I would like to insert break point at a position listed in the below quote. Let's say the below quote belongs to a js file called "test.js". What I would like to do is when I run "node test.js" on the command line, it will break at the break point and then I can inspect all the variables available at the break point.
var a = 4;
function changeA(input) {
var input = 6
[INSERT BREAK POINT HERE]
console.log(input)
};
changeA(a);
console.log(a);
Or is there another way to insert break point to a javascript file?
What you're looking for is the statement debugger;. You can insert that wherever you want, and if you run node debug test.js node will break wherever you placed the debugger; line.
Some of the basic commands once in debugging mode are:
c: continue
n: step next
s: step in
You also have the ability to set breakpoints manually once in debug mode, through the following command: setBreakpoint(line).
Hope this helps!
Resource: NodeJS Debugger API
You can hardcode a breakpoint like this:
debugger;
E.g.:
function changeA(input) {
var input = 6
debugger;
console.log(input)
}
...but you have to be using a debugger for it to mean anything, such as node-inspector. And if you're using a debugger, you can set breakpoints through the debugger itself (rather than hardcoding them).
Here's an example of debugging a very simple NodeJS script via node-inspector:
Script:
var a = +process.argv[2];
var b = +process.argv[3];
var c = a + b;
console.log("c = " + c);
Command to start node-inspector and pass my script a couple of args:
node-debug temp.js 10 20
A browser pops up with a debugging UI and the program paused. I've set a breakpoint through the UI on the var b = ... line, and then stepped passed it once, so I'm sitting on the var c = a + b; line (which hasn't run yet):
If built-in debugger is not something you want to use, you can try Node Inspector which allows you to debug your app using a nice GUI debug interface inside of a browser.
So i'm trying to run some tests with jasmine but i'm fairly new to the whole thing. I've spent way more time than i'm willing to admit trying to work out why my my webdriver is closing the browser before it has a chance to check the '.detailsColumn' element for expected results. After a while I've worked out that i can use browser.wait to make the browser stay alive long enough for the element to be ready.
My latest version of the test is below. The error I get is an invalidSelectorError and no info about which line the error was thrown on. I'd hazard a guess that the invalidSelectorError points to either my declaration or use of the detailsColumn variable though.
Can anyone see why this wouldn't work? I'm at a loss.
I'm using protractor/jasmine to do my tests, and using selenium for my web driver.
it('Should display result summary correctly when searching for multiple articles only', function () {
var TrackID= ExpectedArticle1Details.TrackingID + ', ' + ExpectedArticle2Details.TrackingID;
landingPage.get();
landingPage.setTrackID(TrackID)
landingPage.clickTrackButton();
expect(resultPage.allElementsofLandingPageAreVisible()).toEqual(true);
expect(resultPage.allHeadersofResultsPageAreVisible()).toEqual(true);
browser.wait(function () {
var detailsColumn = protractor.By.css('.detailsColumn.status:eq(0)');
return browser.isElementPresent(detailsColumn).then(function (result) {
expect(result).toBe(true);
return result;
console.log(result);
});
}, 10000);
JQuery index-related selectors like eq() are not supported by selenium webdriver.
You probably want to use nth-child instead:
.detailsColumn.status:nth-child(1)
Or, you may even replace it with element.all() plus first():
element.all(by.css(".detailsColumn.status")).first();
Additionally, if you have to use browser.wait(), I think you can replace the whole browser.wait() block you currently have with:
var EC = protractor.ExpectedConditions;
var detailsColumn = element(by.css('.detailsColumn.status:nth-child(1)'));
browser.wait(EC.presenceOf(detailsColumn), 10000);