Нello! I'm running a clustered node project with a number of nodes. They do a fair bit of console output. I also want to be able to do beautiful coloured output.
My problem: I'm getting jumbled, race-condition-y console output ONLY WHEN USING COLOURS.
I've been boiling things down to isolate my issue, and my current setup is for every node in the cluster to have its own unique string. This is the only string the node will output to console.
let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
return chars[Math.floor(Math.random() * chars.length)].repeat(100);
};
I run a bunch of nodes which are using this function to determine their unique strings, and I see something like the following:
Isn't that beautiful! No matter how long and how furiously all those nodes output, this console output never gets jumbled.
Now, I try with unique strings which contain just a tiny bit of colour:
let chars = 'abcdefghijklmnopqrstuvwxyz1234567890ABCDEFGHIJKLMNOPQRSTUVWXYZ';
let getMyUniqueString = () => {
let redEscSeq = '\x1b[41m';
let clearEscSeq = '\x1b[0m';
let aRedBoxOfText = redEscSeq + ' ' + clearEscSeq;
let repeatedChars = chars[Math.floor(Math.random() * chars.length)].repeat(100);
return aRedBoxOfText + repeatedChars;
};
And look how sad some of my results look!
The ONLY way data is being sent to the terminal, across all nodes, is through the console.log function.
Why is console.log smart enough to keep the output from many nodes unjumbled when there is no colour, but not smart enough to do it when even a bit of colour is included??
Thanks for any help!
(Just for reference, the following image is the kind of unjumbled output I'd expect to see consistently in the coloured case; it's just a red box (two spaces with red background colour) prefixing each line:)
EDIT: While this problem exists in the native windows "cmd.exe" console, in the powershell console, and in ConEmu (a nice 3rd party windows terminal shown in the screenshots), it does NOT exist in the Cygwin terminal! In Cygwin there is never any jumbling, even with tons of colours and async output. Is there anything I can do to encourage this Cygwin behaviour in other consoles??
It is a race condition, and it's unlikely you can do anything about it, maybe except reporting a bug to library used by nodejs.
While windows API itself does in fact support printing multi-colored string in a single API call, as shown here: https://learn.microsoft.com/en-us/windows/console/writeconsoleoutput, where every character contains its color information. But it also doesn't support ANSI escape codes. And this is not what's actually used by javascript.
Nodejs engine uses a library called libuv to write strings to terminal, which is crossplatform and internally translates ANSI escape codes to do the right thing. But if you look closely at the source of libuv for handling ANSI escape codes, you will see that it does a complete buffer flush after every escape code, meaning at some poiint it has to become multiple windows API calls to print one line of text.
Under normal circumstances this is obviously not an issue, but if you have multiple threads doing the writing, it means that parts of those lines may become jumbled... just like what you see here.
So the answer here is that there is no solution. Or you accept using cygwin as a solution.
Related
I'm trying to scan a .txt file in a node.js script, and scan its contents for certain pieces of data. The lines I'm interested in getting look mostly like this:
DIBH91643 5/10/2019 108,75
SIR108811 5/10/2019 187,50
SIR108845 5/10/2019 63,75
So I've been trying to match them with a regex without succes. Using a regex testing site, I've even confirmed the fact that it should find the matches I'm looking for, but it always returns null when I call data.match(regex). I'm probably missing something basic here, but I can't figure it out for the life of me. This is the code I'm using (in its entirety, since there isn't much):
var fs = require('fs');
let regex = /\w*?(\d+)\s+(\d+\/\d+\/\d+)\s+(\-{0,1}\d+\,\d+)/g;
let ihateregex = /91/g;
fs.readFile('pathToFile/fileToRead.txt',{encoding: 'utf-8'}, (err, data) => {
var result = data.match(regex);
console.log(result);
});
As shown, even an attempt with a simple pattern that is definitely inside the file still returns null. I have looked into other answers here for similar problems, and they all point to deleting bytes from the beginning of the file. I have used vim -b to delete the first 2 bytes - which did look out of place and furthermore printing the entire data with console.log() did actually show 2 weird characters in the beginning of the file, but I get the exact same error.
I can't figure out what I'm missing here.
Try the following regex:
/^[A-Z]*(\d+)\s+(\d+\/\d+\/\d+)\s+(-?\d+,\d+)/gm
Improvements compared to your regex:
^ - start from the start of line,
[A-Z]* instead of \w*? - note that \w matches also digits,
removed / in front of - and ,,
? instead of {0,1},
added m option (I assume that you want to process all rows, not the first only).
To process the matches I used the following code, using rextester.com, so
instead of e.g. console.log(...) it contains print(...):
let data = 'DIBH91643 5/10/2019 108,75\nSIR108811 5/10/2019 187,50\nSIR108845 5/10/2019 63,75'
print("Data: ")
print(data)
let re = /^[A-Z]*(\d+)\s+(\d+\/\d+\/\d+)\s+(-?\d+,\d+)/gm
print("Result: ")
while ((matches = re.exec(data)) != null) {
print(matches[1], '_', matches[2], '_', matches[3])
}
For a working example see https://rextester.com/PZU21213
So I've finally figured out what went wrong and I feel extremely stupid for taking so long to figure it out. One thing I've failed to mention even though I should have is that the file I'm reading is one created by an OCR program. An OCR program which, apparently, added an invisible char between each character in the text file, that I only saw when I switched to php (fopen(), fgets(), fclose()) and looked at the source of the page I made.
Once I copied the contents of fileToRead.txt into a newly created fileToRead2.txt (simple copy-paste), it worked perfectly.
As u can see on the image, after every line, an automatic output appears. I want do disable this. I do not intend to use it as a workaround editor, the problem is that on some functions this output is more than some screens big and is hard to look at the expected result.
The default CLI, IIRC, uses the standard Node REPL, but does not provide a trivial way to customize it.
You could start your own REPL and provide options as described in the REPL docs, specifically focusing on:
eval
ignoreUndefined
The easiest solution is to append something to whatever is returning the long value, e.g., if there's a function called foo that returns an object that spans pages, like:
> foo()
// countless lines of output
Tack on something to the command, like:
> foo(); null
null
Below is a code snippet that I get from the internet as an example. Say we are at line 48 (the secong input near the bottom), however, we need to go back to the second of at line 8.Do we just hit :82o?
What if the line number is really large (e.g., 1425) and there are a few of the same word within the line.
In this case, it will take many key strokes, even I have to hit w after I get to the line. How can VIM compete with a mouse in a scenario of random access of a certain word in a large file, in which case you just need to move your pointer with the mouse to achieve this?
Edit: The code is a snippet that I got from the internet in order to demostrate my question. The possible scenario could be I am working on line 1148 and I'd like to go back to line 1108 just to change a word in a comment or I need to fix a bug by making a little bit change within the line 1108. Therefore, the place to go back is hardly predictable and pretty much random.
Edit: I would prefer to know a best practice to achieve this with a vanilla Vim. But you can feel free to provide a solution based on a plugin.
<HTML>
<HEAD><TITLE> Banner</TITLE>
<SCRIPT LANGUAGE= "javascript">
// Puts the text to scroll into variable called sent - SECTION A
// uses length propert to assess its length and put into variable slen
// initalizes a,b,n, and subsent variables
var sent = "This is a demonstration of a banner moving from the left to right. It makes use of the substring property of Javascript to make an interesting display"
var slen = sent.length
var siz = 25
var a = -3, b = 0
var subsent = "x"
// Creates a function to capture substrings of sent - SECTION B
function makeSub(a,b) {
subsent = sent.substring(a,b) ;
return subsent;
}
//Creates a function that increments the indexes of the substring - SECTION C
//each time and calls the makeSub() function to geneate strings
//a indicates start of substring and siz indicates size of string required
function newMake() {
a = a + 3;
b = a + siz
makeSub(a,b);
return subsent
}
//function uses loop to get changing substrings of target - SECTION D
//repeatedly calls newMake to get next substring
//uses setTimeout() command to arrange for substrings to display
// at specified times
function doIt() {
for (var i = 1; i <= slen ; i++) {
setTimeout("document.z.textdisplay.value = newMake()", i*300);
setTimeout("window.status = newMake()", i*300);
}
}
</SCRIPT>
</HEAD>
<BODY >
<HR> <CENTER>
<FORM NAME="z">
<INPUT NAME="textdisplay" TYPE="text" SIZE=25> <P>
<INPUT NAME="doit" Type="button" value = "Run Banner" onClick = "doIt()">
</FORM></CENTER>
<HR>
</BODY></HTML>
Best way to navigate if you know which word you should end up at is to search for it.
I'd do a /of to search for of and I'm there.
I find this easier than moving my mouse pointer.
Now coming to the scenario of really large files, relativenumbers can help you.
set relativenumber
Now to go from 1148 to 1104, you can just do a 40k then use f to get to desired character.
You can prefix f with numbers to move to nth appearance of that character. You can search too.
Again I find this easier than using mouse.
If you have enough command over searching and moving with jk prefixed with motion numbers, you'll be faster than using mouse.
Editing is not something you do at random like in your example. Navigation usually happens from one point of interest to another related point of interest, whether both POIs are part of the same task or parts of related tasks.
Your first example is very unrealistic for two reasons:
because there would be no reason whatsoever to jump from that first POI to that second POI as they are completely unrelated,
because the whole file may not fit wholly in the editing window, which would make the mouse largely irrelevant.
The only potentially useful navigation from your initial state would be to jump to the definition of the event handler, which is only a ?do<CR> away. Note that the function is already under our nose so there's no need to navigate to begin with if all we want is to know what doIt() does.
Your second example is too abstract to work with.
The local navigation tools at your disposal correspond to various zoom levels:
gegEbBwWeE at the word level,
fFtT;,0^$g_g^g$ at the line level,
(){} at the paragraph level,
ggnG at the buffer level,
nHMnL at the window level,
and a bunch of other commands at various levels like hjkl or gm.
But the most powerful of the lot is search, ?/nN (together with set incsearch), which lets you jump directly to wherever you want with minimal effort.
Keyword Search
For random access, keyword search using \{keyword} is normally your best option. Although I have a feeling that this question (with its use of the word of) was geared to sabotage this method, I will point out that you could still run this search by just continuing to type the next word after of. With this approach we are looking at 5-7 keystrokes at most I'd say. That's quite a lot better than using the mouse if you ask me.
EasyMotion
Several others have mentioned the EasyMotion project. I am not too familiar with this project so I will not comment on it any further.
Why to really avoid the mouse?
I do not believe that the added efficiency one acquires by using Vim is the result of avoiding the mouse at all costs; rather, it is the result of training yourself to avoid leaving the home row at all costs. It is not the mechanics of the mouse but the constant task-switching between keyboard to mouse that slows us down the most.
this is my first time asking a question so let me know if I am doing something wrong (post wise)
I am trying to create a function that writes into a .txt but i seem to get two very different results between calling it from within a module, and writing the same loop in the shell directly. The code is as follows:
def function(para1, para2): #para1 is a string that i am searching for within para2. para2 is a list of strings
with open("str" + para1 +".txt", 'a'. encoding = 'utf-8') as file:
#opens a file with certain naming convention
n = 0
for word in para2:
if word == para1:
file.write(para2[n-1]+'\n')
print(para2[n-1]) #intentionally included as part of debugging
n+=1
function("targetstr". targettext)
#target str is the phrase I am looking for, targettext is the tokenized text I am
#looking through. this is in the form of a list of strings, that is the output of
#another function, and has already been 'declared' as a variable
when I define this function in the shell, I get the correct words appearing. However, when i call this same function through a module(in the shell), nothing appears in the shell, and the text file shows a bunch of numbers (eg: 's93161), and no new lines.
I have even gone to the extent of including a print statement right after declaration of the function in the module, and commented everything but the print statement, and yet nothing appears in the shell when I call it. However, the numbers still appear in the text file.
I am guessing that there is a problem with how I have defined the parameters or how i cam inputting the parameters when I call the function.
As a reference, here is the desired output:
‘She
Ashley
there
Kitty
Coates
‘Let
let
that
PS: Sorry if this is not very clear as I have very limited knowledge on speaking python
I have found the solution to issue. Turns out that I need to close the shell and restart everything before the compiler recognizes the changes made to the function in the module. Thanks to those who took a look at the issue, and those who tried to help.
I tried the following snippet of Alloy4, and found myself confused by the behavior of the util/Natural module. The comments explain more in detail what was unexpected. I was hoping someone could explain why this happens.
module weirdNatural
private open util/natural as nat
//Somehow, using number two obtained from incrementing one works as I expect, (ie, there is no
//number greater than it in {0,1,2}. but using number two obtained from the natrual/add function
//seems to work differently. why is that?
let twoViaAdd = nat/add[nat/One, nat/One]
let twoViaInc = nat/inc[nat/One]
pred biggerAdd {
some x: nat/Natural | nat/gt[x, twoViaAdd]
}
pred biggerInc {
some y: nat/Natural | nat/gt[y, twoViaInc]
}
//run biggerAdd for 10 but 3 Natural //does not work well, it does find a number gt2 in {0,1,2}
run biggerInc for 10 but 3 Natural //works as expected, it finds a number gt2 in {0,1,2,3}, but not in {0,1,2}
Thanks for this bug report. You are absolutely right, that is a weird behavior.
Alloy4.2 introduced some changes to how integers are handled; namely, the + and - operators in Alloy4.2 are always interpreted as set union/difference, so built-in functions plus/minus have to be used to express arithmetic addition/subtraction. On the other side, the util/natural module (mistakenly) hasn't been updated to use the latest syntax, which was the root cause of the weird behavior you experienced (specifically, the nat/add function uses the old + operator instead of plus, whereas nat/inc doesn't).
To work around this issue, you can either
open the util/natural module (choose "File -> Open Sample Models" from the main menu)
edit the file and replace the two occurrences of <a> + <b> with plus[<a>, <b>]
save the new file in the same folder with your model als file (e.g., as "my_nat.als")
open it from your main module (e.g., open my_nat as nat)
or
download the latest unofficial version where this bug is fixed (you might need to manually delete the Alloy temp folder to make sure that the Alloy Analyzer is not using the old (cached) version of the util/natural library).