Groovy: How to write on a line on the same position on screen? (Windows) - groovy

I want to show advance % in groovy , so I want to write on the same position, which means that instead of seeing:
1%
2%
3%
...
The user will see the figures changing in the same location.
How do I do that? (I'm working on windows)

I do this frequently just using a carriage return without a line feed:
printf "%5d\r", loopval
Each time through your loop, printing will start over again at the beginning of the line.
It can get a tad messy if any other messages should print out while this is happening, especially if the other message contain newlines. But it's a cheap and dirty solution.

You can use jline that comes with Groovy:
(1..5).each {
print "Done $it of 5"
Thread.sleep( 1000 )
print jline.ANSIBuffer.ANSICodes.left( 9999 )
}
So long as your console supports ANSI escape sequences, that should work...
PS: I used 9999 because (as it says in the documentation for left)
If n is greater or equal to the current cursor column, the cursor is moved to the first column

For anyone who comes across this - I found using the following to be the best solution:
(0..100).each {
print "\r$it%"
}
println()

as Danny Y. already stated, a line feed will work, backspaces will also do the trick:
(0..100).each {
print "\b"*20+it+"%"
sleep 100
}
I once had to overwrite a multipline output - the solution I found was to
print "\r\n"*80
in order to scroll all old content out of the screen - not a nice solution, but it work on windows shell :-)

Related

Is there an end= equivalent for inputs?

So as I'm sure you know there's a specific operator for print() functions called end.
#as an example
print('BOB', end='-')
#would output
BOB-
So is there something like this for inputs? For example, if I wanted to have an input that would look something like this:
Input here
►
-------------------------------------------------------
And have the input at the ► and be inside the dashes using something like
x = input('Input here\n►', end='-------')
Would there be some equivalent?
EDIT:
Just to be clear, everything will be printed at the same time. The input would just be on the line marked with the ►, and the ---- would be printed below it, but at the SAME time. This means that the input would be "enclosed" by the ---.
Also, there has been a comment about curses - can you please clarify on this?
Not exactly what you want, but if the --- (or ___) can also be on the same line, you could use an input prompt with \r:
input("__________\r> ")
This means: print 10 _, then go back \r to the beginning of the line, print > overwriting the first two _, then capture the input, overwriting more _. This shows the input prompt > ________. After typing some chars: > test____. Captured input: 'test'
For more complex input forms, you should consider using curses.
When using basic console IO, once a line has been ended with a newline, it's gone and can't be edited. You can't move the cursor up to do print anything above that last line, only add on a new line below.
That means that without using a specialized "console graphics" library like curses (as tobias_k suggests), you pretty much can't do what you're asking. You can mess around a little with the contents of the last line (overwriting text you've already written there), but you can't write to any line other than the last one.
To understand why console IO works this way, you should know that very early computers didn't have screens. Instead, their console output was directly printed out one line at a time on paper. While some line printers could print several characters on the same spot (to get effects line strikethrough or underline), you couldn't unprint anything once it was on the paper. Furthermore, the paper feed only worked in one direction. Once you had sent a newline character that told the printer to advance the paper, you couldn't go back to an old line again.
I believe this would solve your problem:
print(f">>> {input()} ------")
OR
print(f"{input(">>>")} ------")
F-strings are quite useful when it comes to printing text + variables.

How to go up a line in Console Programs (C++)

In C++ I'm trying to go back up a line to add some characters.
Here is my code so far:
cout << "\n\n\n\n\n\n\n\n\n\n\xc9\xbb\n\xc8\xbc"<<flush;
Sleep(50);
As you can see, I have 10 newline characters. In my animation, a new block will be falling from the top of the screen. But I don't know how to go back up those lines to add the characters I need. I tried \r, but that dosen't do anything and \b dosen't go up the previous line either. Also, what exactly does flush do? I've only been programming in C++ for about 2 days so I'm a newb =P.
Thanks so much!!!
Christian
If your console supports VT100 escape sequences (most do), then you can use ESC [ A, like this:
cout << "\x1b[A";
to move the cursor up one line. Repeat as necessary.
In windows you can use this example
there you will create CreateConsoleScreenBuffer()
and then are using SetConsoleCursorPosition(console_handle, dwPosition);
cout will first write to internal buffer and only output it to the screen periodically and not for every character that gets inserted. This is for performance reasons.
flush tells it to empty the buffer now and show it on screen.
You should consider a library like ncurses.

Using sed to print range when pattern is inside the range?

I have a log file full of queries, and I only want to see the queries that have an error. The log entries look something like:
path to file executing query
QUERY
SIZE: ...
ROWS: ...
MSG: ...
DURATION: ...
I want to print all of this stuff, but only when MSG: contains something of interest (an error message). All I've got right now is the sed -n '/^path to file/,/^DURATION/' and I have no idea where to go from here.
Note: Queries are often multiline, so using grep's -B sadly doesn't work all the time (this is what I've been doing thus far, just being generous with the -B value)
Somehow I'd like to use only sed, but if I absolutely must use something else like awk I guess that's fine.
Thanks!
You haven't said what an error message looks like, so I'll assume it contains the word "ERROR":
sed -n '/^MSG.*ERROR/{H;g;N;p;};/^DURATION/{s/.*//;h;d;};H' < logname
(I wish there were a tidier way to purge the hold space. Anyone?...)
I could suggest a solution with grep. That will work if the structure in the log file is always the same as above (i.e. MSG is in the 5th line, and one line follows):
egrep -i '^MSG:.*error' -A 1 -B 4 logfile
That means: If the word error occurs in a MSG line then output the block beginning from 4 lines before MSG till one line after it.
Of course you have to adjust the regexp to recognize an error.
This will not work if the structure of those blocks differs.
Perhaps you can use the cgrep.sed script, as described by Unix Power Tools book

How do I grep for entire, possibly wrapped, lines of code?

When searching code for strings, I constantly run into the problem that I get meaningless, context-less results. For example, if a function call is split across 3 lines, and I search for the name of a parameter, I get the parameter on a line by itself and not the name of the function.
For example, in a file containing
...
someFunctionCall ("test",
MY_CONSTANT,
(some *really) - long / expression);
grepping for MY_CONSTANT would return a line that looked like this:
MY_CONSTANT,
Likewise, in a comment block:
/////////////////////////////////////////
// FIXMESOON, do..while is the wrong choice here, because
// it makes the wrong thing happen
/////////////////////////////////////////
Grepping for FIXMESOON gives the very frustrating answer:
// FIXMESOON, do..while is the wrong choice here, because
When there are thousands of hits, single line results are a little meaningless. What I would like to do is have grep be aware of the start and stop points of source code lines, something as simple as having it consider ";" as the line separator would be a good start.
Bonus points if you can make it return the entire comment block if the hit is inside a comment.
I know you can't do this with grep alone. I also am aware of the option to have grep return a certain number of lines of context. Any suggestions on how to accomplish under Linux? FYI my preferred languages are C and Perl.
I'm sure I could write something, but I know that somebody must have already done this.
Thanks!
You can use pcregrep with the -M option (multiline matching; pcregrep is grep with Perl-compatible regular expressions). Something like:
pcregrep -M ";*\R*.*thingtosearchfor*\R*.*;.*"
Here's an example using awk.
$ cat file
blah1
blah2
function1 ("test",
MY_CONSTANT,
(some *really) - long / expression);
function2( one , two )
blah3
blah4
$ awk -vRS=")" '/function1/{gsub(".*function1","function1");print $0RT}' file
function1 ("test",
MY_CONSTANT,
(some *really)
the concept behind: RS is record separator. by setting it to ")", then every record in your file is separated by ")" instead of newline. This make it easy to find your "function1" since you can then "grep" for it. If you don't use awk, the same concept can be applied using "splitting" on ")".
You can write a command line using grep with the options that give you the line number and the filename, then xarg these results into awk to parse these columns and then use a little script from you to display the N lines surrounding that line? :)
If this isn't an academic endeavour you could just use cscope (for C code only though). If you are willing to drop the requirement to search in comments ctags should be enough (and it also supports Perl).
I had a situation in which I had an xml file full of the names of zip files in an xml style format, that is, with carrots bracketing the names of the files, say example.zip<\stuff>
I used awk to change all carrots into newlines then used grep :)

How do I erase printed characters in a console application(Linux)?

I am creating a small console app that needs a progress bar. Something like...
Conversion: 175/348 Seconds |========== | 50%
My question is, how do you erase characters already printed to the console? When I reach the 51st percentage, I have to erase this line from the console and insert a new line. In my current solution, this is what happens...
Conversion: 175/348 Seconds |========== | 50%
Conversion: 179/348 Seconds |========== | 52%
Conversion: 183/348 Seconds |========== | 54%
Conversion: 187/348 Seconds |=========== | 56%
Code I use is...
print "Conversion: $converted_seconds/$total_time Seconds $progress_bar $converted_percentage%\n";
I am doing this in Linux using PHP(only I will use the app - so please excuse the language choice). So, the solution should work on the Linux platform - but if you have a solution that's cross platform, that would be preferable.
I don't think you need to apologize for the language choice. PHP is a great language for console applications.
Try this out:
<?php
for( $i=0;$i<10;$i++){
print "$i \r";
sleep(1);
}
?>
The "\r" will overwrite the line with the new text. To make a new line you can just use "\n", but I'm guessing you already knew that.
Hope this helps! I know this works in Linux, but I don't know if it works in Windows or other operating systems.
To erase a previously printed character you have three options:
echo chr(8) . " "; echoes the back character, and will move the cursor back one place, and the space then overwrites the character. You can use chr(8) multiple times in a row to move back multiple characters.
echo "\r"; will return the cursor to the start of the current line. You can now replace the line with new text.
The third option is to set the line and column of the cursor position using ANSI escape codes, then print the replacement characters. It might not work with all terminals:
function movecursor($line, $column){
echo "\033[{$line};{$column}H";
}
\r did the trick.
For future reference, \b does not work in PHP in Linux. I was curious - so I did a couple of experiments in other languages as well(I did this in Linux - I don't know if the result will be the same in Windows/Mac)..
\b Works in...
Perl
Ruby
Tcl - with code puts -nonewline "Hello\b"
\b Doesn't work in
PHP - the code print "Hello\b"; prints out Hello\b
Python - code print "Hello\b" prints out Hello<new line> . Same result with print "Hello\b",
I'm not sure if it's the same in Linux but in Windows console apps you can print \r and the cursor will return to the first left position of the line allowing you to overwrite all the characters to the right.
You can use \b to move back a single character but since you're going to be updating your progress bar \r would be simpler to use than printing \b x number of times.
This seems to be pretty old topic but I will drop my 5 into.
for ($i; $i<_POSITION_; $i--) {
echo "\010"; //issue backspace
}
Found this on the internet some time ago, unfortunately don't remember where. So all credits goes to original author.
to erase a previously printed character, I print a backspace after it:
print "a"
print "\b"
will print nothing (actually it will print and then a backspace, but you probably won't notice it)

Resources