How do I clear the current line of stdout? - rust

I'm trying to make a status indicator in Rust that prints to stdout. In other languages, I've used a function that clears the current line of stdout while leaving the others untouched. I can't seem to find a Rust equivalent. Is there one? Here's a small example of what I'm looking for
for i in 0..1000 {
stdio::print(format!("{}", i).as_slice));
stdio::clear();
}

On an ANSI terminal (almost everything except Command Prompt on Windows), \r will return the cursor to the start of the current line, allowing you to write something else on top of it (new content or whitespace to erase what you have already written).
print!("\r")
There is nothing available in the standard library to do this in a platform-neutral manner.

Utilizing the ASCII code for backspace is one option, for example:
print!("12345");
print!("{}", (8u8 as char));
This will end up outputting "1234" after the 5 is removed as a result of printing the backspace character (ascii code 8). Strangely, Rust does not recognize \b as a valid character escape.

Related

how to delete already printed text on terminal screen before printing the next text on rust?

I have printed the text using print! print!("Hello world")now I want to clear the this text before printing the next text print!("hello rust")I found this crate clear screen but this clears the whole terminal instead of the already printed text. I just want to clear the printed text and the not the whole terminal.
You can print a \x08 or "backspace" character to move the curser back one spot. Or you can use \r to move it to the start of the line. Neither option will actually erase characters so you need to print spaces to fill them up.
use std::io::prelude::*;
fn main() {
// print some text
print!("abcdefgh");
// Flush, by default input is buffered and only sent at the end of the line. Thus we must flush for the text to appear.
std::io::stdout().flush().unwrap();
// Wait 0.5 seconds, this is just to demonstrate the effect.
std::thread::sleep(std::time::Duration::from_secs_f32(0.5));
// Print 8 backspace characters, clearing the line.
print!("\r{}\r", " ".repeat(8));
}
This only works if the line has not yet ended, however, there are ANSII escape codes available to move the cursor up if you have reached the end of the line. See https://en.wikipedia.org/wiki/ANSI_escape_code for more info.
If you want to print the previous line instead use this:
fn main() {
// print some garbage, with a line break at the end
println!("abcdefgh");
// again just a sleep just to the effect is visible
std::thread::sleep(std::time::Duration::from_secs_f32(0.5));
// move up one then replace all the text with spaces to hide it
println!("\x1b[1;A{}", " ".repeat(8));
}
Note that this is all very terminal specific. These command work differently on windows vs linux and different linux distributions.

Norminette empty line or not at end

Why people on VStudio with norminette highlights put an empty line at end.
And when they do norminette in iTerm it’s Works
When you use Vim and put an empty line at end the norminette say Error extra line.
This happen yesterday and today my Vstdio ask for a line at end and when I do norminette in iTerm it’s say error extra line. I go back to vim, delete the line and norminette say error again to remove extra line. I need to open back the file, add line and then delete and save to have norminette working. So now sometime moulinette say KO on server but OK my side. I need to add/remove last line every time with vim when I work on vstdio
So if someone know the issue i would like to have a better solution than double check on vim for the next 3 week and maybe 3 years 🤣 thx all!
That topic has already been discussed to death.
No matter what system you are on, lines in text files generally end with one or two invisible characters. On some systems, it's a "carriage return" CR followed by a "line feed" LF, on other systems it's only a CR, on other systems it's only a LF, and that's only for the least exotic ones. That character or pair of characters has a few colloquial names: "newline", "EOL", etc. I will use "EOL" from now on.
Now, EOL has two semantic interpretations. In some contexts, EOL is considered to be a "line terminator", meaning that no assumption is made about what comes after it, and in some other contexts, EOL is considered to be a "line separator", meaning that there is always a line after it.
And then there is the related problem of how a stream of text should end. With the first interpretation, the last line of a stream should end with EOL, if only to be able to establish a boundary between two streams. With the second interpretation above, the last line of a stream shouldn't end with EOL because it would mean… that the last line is not really the last line.
So, basically, this text:
foo
bar
baz
could be encoded as (first interpretation):
foo<EOL>
bar<EOL>
baz<EOL>
or as (second interpretation):
foo<EOL>
bar<EOL>
baz
Most Unix-like tools have adopted the first interpretation for decades and generally expect EOL on the last line but many more modern tools have adopted the second interpretation, which leads to much confusion among new generations who juggle between GUI editors and CLI tools.
Feed some text with a final EOL to a tool that interprets it as a "line separator" and you get an imaginary line displayed at the end of the file:
1 foo
2 bar
3 baz
4
Feed some text without a final EOL to a tool that interprets it as "line terminator" and you can get anything from a reasonable display (as follows) to loud complaints (git):
1 foo
2 bar
3 baz
Add to that confusing names like "newline" and you have a recipe for a never-ending stream of questions like this one.
So… this is what seems to be going on, here:
you are using a mix of tools that interpret EOL differently,
you are interpreting one of those interpretations incorrectly,
and you act upon that misinterpretation, with confusing results.
Let's address these one-by-one.
Well, we all do so ¯\_(ツ)_/¯.
What appears like an extra line at the bottom of your file in a modern GUI editor is unlikely to be an extra line. It is more likely to be an artefact of the second interpretation. Assuming you are on some kind of Unix-like system and the expected EOL is LF, you can do $ xxd filename to inspect its content in hexadecimal form:
a single a0 at the end means that your file ends with EOL,
a a0a0 at the end means that your file has an extra empty line,
no a0 at the end means that it was written by a an editor that firmly adheres to the second interpretation.
The second case will angry your linter:
Error: EMPTY_LINE_EOF (line: 7, col: 1): Empty line at end of file
but it doesn't seem to particularly care about the other two cases.
Because you see what appears to be an empty line at the end of a file in a GUI editor it doesn't mean that a) that line actually exists and b) that you must add one at the end of the file in Vim or any other editor.
The correct approach is to:
let Vim do what it does out the box, write files with an EOL at the end, because that's what your toolchain (including Norminette) expects,
set up your GUI editors to do the same (even if they still show that imaginary line),
get rid of any extraneous empty line you might have in one of your projects,
NEVER add an extraneous empty line at the end of your files, as it useless at best and forbidden at worst.

How to delete, including the current character?

Let's say I've typed "abcdefg", with the cursor at the end. I want to delete back to the c, so that I only have "abc" left.
Is there a command like d that includes the current character? I know I could do dTcx, but the x feels like a work-around and I suppose there's a better solution.
No. Backward motions always start on the left of the current character for c, y and d which is somehow logical but also unnerving.
The only "clean" solutions I could think of either imply moving to the char after c first and then do a forward delete:
Tcde
or using visual mode:
vTcd
v3hd
But, given your sample and assuming you are entering normal mode just for that correction, the whole thing sounds extremely wasteful to me.
What about staying in insert mode and simply doing ←←←←?
try this:
TcD
this will leave abc for your example... well if the abcdefg is the last word of the line.
if it is not the last word in that line, you may do:
ldTc
or golfing, do it within 3 key-stroke:
3Xx or l4X
See this answer to a similar question : there is a setting to be allowed to go beyond the end of the line
From the doc :
Virtual editing means that the cursor can be positioned where there is
no actual character. This can be halfway into a tab or beyond the end
of the line. Useful for selecting a rectangle in Visual mode and
editing a table.
"onemore" is not the same, it will only allow moving the cursor just
after the last character of the line. This makes some commands more
consistent. Previously the cursor was always past the end of the line
if the line was empty. But it is far from Vi compatible. It may also
break some plugins or Vim scripts. For example because |l| can move
the cursor after the last character. Use with care!
Using the $ command will move to the last character in the line, not
past it. This may actually move the cursor to the left!
The g$ command will move to the end of the screen line.
It doesn't make sense to combine "all" with "onemore", but you will
not get a warning for it.
In short, you could try :set virtualedit=onemore, and see if your environment is stable or not with it.
Use d?c
That will start d mode, search back to 'c' and then delete up to your cursor position.
Edit: nope, that does not include current position...
I may be misunderstanding your request, but does 3hd$ do it?
I would use vFdd in this example. I think it's nicer than the other solutions since the command explicitly shows what to delete. It includes the current character and the specified character when deleting.
v: enter visual mode (mark text)
F: find/goto character backwards
d: the character "d" that will be included for removal.
d: delete command
Since it is visual mode, the cursor can also be moved before executing the actual removal d. This makes the command powerful even for deleting up to a non unique character by first marking a special character close to the character and then adjusting the position.

How to have a carriage return without bringing about a linebreak in VIM?

Is it possible to have a carriage return without bringing about a linebreak ?
For instance I want to write the following sentences in 2 lines and not 4 (and I do not want to type spaces of course) :
On a ship at sea: a tempestuous noise of thunder and lightning heard.
Enter a Master and a Boatswain
Master : Boatswain!
Boatswain : Here, master: what cheer?
Thanks in advance for your help
Thierry
In a text file, the expected line-end character or character sequence is platform dependent. On Windows, the sequence "carriage return (CR, \r) + line feed (LF, \n)" is used, while Unix systems use newline only (LF \n). Macintoshes traditionally used \r only, but these days on OS X I see them dealing with just about any version. Text editors on any system are often able to support all three versions, and to convert between them.
For VIM, see this article for tips how to convert/set line end character sequences.
However, I'm not exactly sure what advantage the change would have for you: Whichever sequence or character you use, it is just the marker for the end of the line (so there should be one of these, at the end of the first line and you'd have a 2 line text file in any event). However, if your application expects a certain character, you can either change the application -- many programming languages support some form of "universal" newline -- or change the data.
Just in case this is what you're looking for:
:set wrap
:set linebreak
The first tells vim to wrap long lines, and the second tells it to only break lines at word breaks, instead of in the middle of words when it reaches the window size.

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