Go Premium for a chance to win a PS4. Enter to Win

x
  • Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 711
  • Last Modified:

Creating a Command Line Interface in Linux

I'm trying to create a simple command line interface on Linux, using the termios API.  Basically, the only features I really want are a simple prompt, line-based input, the ability to edit/delete characters on a line before hitting enter, and a "history" vector which can be accessed by hitting the up arrow key.  A simple call to fgets will not be adequate here, because the user would not be able to use the arrow keys to edit input.  

Unfortunately, there are very few tutorials on the workings of termios, and indeed it seems the termios API is quite in depth and sophisticated.

However, I seem to have a basic understanding of what needs to be done here.  Firstly, I would need to set the terminal to non-canonical mode in order to process each key press individually.  My question is, on non-canonical mode, how do I change the actual on-screen output that the user has typed, if the user decides to edit an input string while typing?

For example, suppose the user types 'abc' and then hits backspace.  In canonical mode, the OS would take care of the backspace and delete the 'c' from the screen.  In non-canonical mode, however, this is not the case.  So how can I replicate backspace functionality in non-canonical mode?  One way that occurred to me would be to simply output a linefeed character, and then reoutput the entire string minus the deleted character, as demonstrated in the code below.  Is this a standard practice, or is there a better way to do this?
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <termios.h>
 
int main(int argc, char *argv[])
{
	struct termios orig, now;
	int i, rc;
	setvbuf(stdout, NULL, _IONBF ,0);
 
	tcgetattr(0, &orig);
	now = orig;
	now.c_lflag &= ~(ICANON | ECHO);
	now.c_iflag;
 
	now.c_cc[VMIN] = 1;
	now.c_cc[VTIME] = 2;
 
	tcsetattr(0, TCSANOW, &now);
 
	bool done = 0;
	char buf[256];
 
	char output[256];
	char* current = output;
	
	while (!done) 
	{
		char c = getchar();
		if (c == now.c_cc[VERASE]) {
			// Clear rest of the line
			putchar('\r');
			for (int i = 0; i < (current - output); ++i) putchar(' ');
 
			putchar('\r');
			--current;
			write(0, output, current - output);
		}
		else {
			putchar(c);
			if (current == output + (sizeof(output) - 1)) current = output; // reset buffer; 
			*current++ = c;
		}
	}
 
	tcsetattr(0, TCSANOW, &orig);
	return 0;
}

Open in new window

0
chsalvia
Asked:
chsalvia
  • 3
  • 2
3 Solutions
 
mrjoltcolaCommented:
Rather than using termios directly, I have done this in years past with curses. I think curses will be easier. See also NCURSES

http://en.wikipedia.org/wiki/Curses_(programming_library)

http://www.linux.org/docs/ldp/howto/NCURSES-Programming-HOWTO/intro.html#WHATIS
0
 
Duncan RoeSoftware DeveloperCommented:
Yes you need to use ncurses to see function (and arrow) keys. Use it for input only - manage your own output.
0
 
Greg_ArnoldCommented:
The easiest way to erase a character is to print a backspace, a space, then another backspace.

Something like this:
putchar('\b');
putchar(' ');
putchar('\b');

Open in new window

0
What does it mean to be "Always On"?

Is your cloud always on? With an Always On cloud you won't have to worry about downtime for maintenance or software application code updates, ensuring that your bottom line isn't affected.

 
mrjoltcolaCommented:
I see no problem with this question, the answers are valid. I recommend force accept, at least the answers regarding NCURSES to manage non-canonical mode.
0
 
Greg_ArnoldCommented:
I agree with mrjoltcola - there are valid answers.  Mostly his, maybe a little of mine.
0
 
mrjoltcolaCommented:
All these answers are appropriate and useful:
http:#24093668
http:#24113023
http:#25998701

Thanks,
-mjc
0

Featured Post

Free Tool: ZipGrep

ZipGrep is a utility that can list and search zip (.war, .ear, .jar, etc) archives for text patterns, without the need to extract the archive's contents.

One of a set of tools we're offering as a way to say thank you for being a part of the community.

  • 3
  • 2
Tackle projects and never again get stuck behind a technical roadblock.
Join Now