It seems that you can go back one character from current line in the console using \b. However, the console doesn't seem to be able to jump one line up.
I want to mark invalid user input red. After typping input, user presses Enter which put's unerasable new line in the console.
My plan was to do the following:
Check the input for validity.
If it's invalid, print input.length()+1 times \b
Turn console color red
Print the input, print \n
But, the \b will not jump back to the line where user input is. So I have plan B:
Remember the length of string that was before user input (query_string)
Check the input for validity.
If it's invalid, go line up (where the input was entered)
Jump to query_string.length() character
Turn console color red
Print the input, print \n
However, I don't know how to do this using the console API.
There are at least two ways you can do this.
One way is, as #chris implied in a comment, is to save the cursor position of where the user started typing. When you find bad input, you set the cursor back to that position and change the text attribute of the characters he entered.
You probably don't want to scroll the window back up one line. If you do, then the window will appear to "jump" when the user makes an error. It's a really jarring user interface experience. But if you want to try, you can call ScrollConsoleScreenBuffer.
Another way to do it would be to change the console mode so that it doesn't automatically echo characters when the user types them. Instead, you read each character individually, append it to your input buffer, and when the user presses Enter you validate. If the input is valid, you issue a newline to move to the next line. Otherwise you back up and highlight the erroneous input. This sounds like a lot more work, but it's not that difficult and it results in a much better UI experience.
Related
I have a list of instructions in my program and they are activated by entering a string. There are a large number of possible instructions. You could call them commands if you like.
I already have a program that can successfully execute the instructions I've added so far.
For example, adding a person to the database would require the user to enter add "John" "Doe".
This would output to the screen Added John Doe to the database, ID#1234. The IDs are random.
I know how to add colors; in this output text, "John Doe" would be colored green.
What I'm wondering is, can I make it so that color changes as one types? Because I learned how to use some kind of keyboard mode change so that when I type a password, all characters are displayed as * of any color I desire, or even nothing displayed at all, through "display" of \0, and I know how to do that. I was wondering if the color could change before the complete string (extracted with std::getline(std::cin, str);) is typed.
The first reason I want the colors to change is because when there are so many commands, and I already have more complex commands than that, I want to provide a way for the user to be able to correct syntax mistakes before they press enter. Something like Windows PowerShell, perhaps, which was written in C#. I know that C# is a very different language than C++, but if C# can achieve something like that, I want to see if C++ can as well. My hope is that it doesn't require thousands of lines of application-specific code, especially considering that PowerShell is an actual application and not a simple terminal-run executable. And while PowerShell appears to be open-source, I don't understand C#. See the bottom for the second reason.
I have no idea if this is possible, but because similar manipulation of entered text is possible (as I said, I know how to add colors and also mask text as some other single character like *), I want to know if this is also possible.
Simple examples:
Firstly, the user should know when they have not entered a valid command, and when they have. I want the text to be in red until the letters entered so far consist of an actual keyword, like add. So, the text would be red until the second d is added, when it reverts to white, and if another letter is entered, it becomes red again.
Example 1: add "John Elias" "Doe"
After the space, the text after "add" should be red no matter what, unless the character after the space is a quotation mark. In order to tell the user that they have not terminated the string, the text beyond the (orange?) quotation mark should be orange. When the final quotation mark is entered, the entire content of the quotation marks (including the quotation marks) should be some other color (probably green?) to tell the user that they have successfully entered an argument. The same applies to any instances of quotation-mark arguments. Note that a space is allowed in a quotation argument.
Example 2: list-info 1234
In this command, it gets more complex. list is a separate command, so the text should be red until t is entered, and it turns white. But then it turns red again after that, until o is entered, and it turns white again. The numerical argument following it should be red if the entered character isn't a digit. If it is, it's still red, because the only valid IDs are 3- or 4-digit numbers. It should turn green(?) once a third digit is entered, and still stay green when another digit is entered. But if a fifth digit is entered (or another character for that matter), the number turns red again. Although this would better be implemented as returning an error if the entered number is invalid, I would still like to know if this can be done as well.
Example 3: add "John" "Elias" "Doe" "fourth-string"
Since there is an overloaded function that enables an explicit first-middle-last name to be stored as well, it should be ok if there is a third string. But if there is a fourth string added, then it should be in red no matter what because add cannot take more than 3 arguments.
My question is, are any of these things possible? And yes, I am aware that it is almost certainly better to just implement an error system, but my intention is to expand my coding ability, and that is the second reason, and coding an error system will not do that because I have already done that for every command.
For reference, I'm operating in Linux Ubuntu 18.04, I compile with g++, my code conforms to C++17, I use ANSI escape sequences for color, bold, etc., and for masking characters with something like * I use a pointer to a char array (passed by address as char**) and a C-style FILE* to reference the input stream stdin (because I haven't bothered to conform it to a typical C++ implementation yet, learning ways to advance my current skills is my priority at this point in time).
Im working on a crude console based text editor in C++ kind of like nano. I've already figured out a basic way of inputting multiple lines of text and writing it to a file correctly (input ends when they enter a code: //end). However, at the moment the user is unable to move upwards (using arrow keys) and edit lines that they have entered. For some additional information I'm doing this with a getline() loop, writing files with ofstream, and am storing the users text in a string vector with each element being an entered line. How might I implement the ability to work with a body of text in such a way?
For advanced use, you need access to the console API.
For a simpler version, look at the primitive visual editors.
Editing a line consists of moving to the line, printing out the content, and then letting them insert or delete characters on that line.
Look at sed or ed or even vi.
Straight to the point. I've been using visual studio to run a game I've been making. So far while coding in C++ I've been using inputs like VK_BACK or 0x52 for single key inputs. But I currently need to be able to type a word while the game is running to trigger a function. Basically, I'm asking how you would go about making the program recognize an inputted word. Like pressing the keys in a sequence to trigger a function.
Thanks, Jack
You've left a lot up to us to guess:
What are you using to read keyboard input?
I assume you're polling rather than streaming?
I'm also assuming non-blocking input?
With so many unknowns it's difficult to give a useful answer to the question. But here are a handful of options that may be helpful to you:
Require a terminating character for all keyboard input. This is characteristic of blocking input. The input is only read when the terminating character is placed.
Require the holding of a mode key while inputting a string. For example if I press an 'a' the key's command is executed immediately, but if I'm currently holding down the left Ctrl key and I press an 'a', it is treated as being within a string until the Ctrl key is released.
Use delimiters. If the '\'' is pressed it denoted the beginning of a string input consisting of all characters till the next '\'' key is pressed.
Make string entry keys separate from instantaneous input keys. This may be the most convenient solution because it allows instantaneous input in the middle of string input. But it may also be frustrating to the user if the allowable string commands are not clearly defined.
I'm using a CRichEditCtrl to edit a computer language, and on every change to it I'm calling SetSelectionCharFormat on the current line of text (as reported by LineFromChar(-1)) to highlight the syntax. (EG: comments in green, section headings in a bigger font, compilation errors in red, etc.) Note this language doesn't have multi-line features such as a C comment where typing /* on one line makes following lines part of a comment too; for any given character change I only need to change the color of the current line.
It all looks like its working fine.
However there are some weird issues. One is, when multiple lines of text is selected from somewhere else, and pasted. My OnUpdate() is called but is naively assuming that the only line that potentially needs re-formatting is the one returned by LineFromChar(). That suffices when the user is typing character by character, but it means that after receiving a multi-line paste, the program only reformats the last line of the pasted text. How can it know where the start of the insert was?
OnUpdate is called inside the Paste operation.
It should be possible to subclass the RTF control and to intercept the WM_PASTE message. If WM_PASTE is not used internally it might be possible to use EM_PASTESPECIAL. If even tis message isn't sent, you have to interecept the Ctrl+V that causes the paste Operation.
Than you can determine the starting position of the paste operation.
Spy++ might be helpful to determine the message flow in the RTF control.
I would like to write 80 (standard conole width) characters in one line without the cursor go to next line. It is only problem when I want to print 80 characters in the last line of console. It cases scrolling that I dont want.
Take a look:
I dont want the newline. any way to do this? :/
Im on Windows, DEV-C++, using WinApi for colors and moving the cursor (the window resize too).
Thanx for any answers.
Instead of using standard output functions use the Windows Console API to set the cursor position and draw characters. Specifically, take a look at WriteConsoleOutput.
MSDN Console API Docs
The only reason why you are on a new line is because the console is not big enought to support the eighty stars.
So it pushed the cursor to the next line.
through one or two "\b" at the end it moves the cursor back.
For the system-critical console window, the cursor should always stay visible, and the only way for it to do so after you've reached the max number of chars in a line, is to pop up on the next visible line (without actually making any new lines).
filter the output either in the originating program or with another program through a pipe. When you have outputted too many characters on a single line, do whatever you like (i.e., drop characters, overwrite, etc....).