0

I want to autocomplete on a command line application a but like in bash you can use tab key which will complete the command. But getchar() seems to wait until a newline char is received before it starts reading any characters.

scanf seems to work the same way.

Is there any way I can scan characters one at a time no matter if they are whitespace or control characters?

I want to be able to read char by char as entered building up a command and then as soon as tab char received I will attempt to lookup how to complete and print full command in my application.

Angus Comber
  • 9,316
  • 14
  • 59
  • 107
  • have looked at how other C programs do that? It's usually a good idea to copy from working code; that's what FOSS is about (and bash, for example is FOSS, but I'd argue that bash is a bit hard to understand in its autocompletion) – Marcus Müller Sep 02 '17 at 22:15
  • 1
    If you really can't use anyone else's work, you have to juggle the terminal attributes to use 'non-canonical' mode. In canonical mode, no input is sent to the program until the user hits return (or uses the control-D (EOF) key). See [Canonical vs non-canonical terminal input](https://stackoverflow.com/questions/358342) for more information. And you have to ensure that the terminal attributes are reinstated before your program exits — and probably when your command line application runs any other program too. That's all hard work; use someone else's hard work instead. – Jonathan Leffler Sep 02 '17 at 22:23
  • 1
    The question is not *nix specific, MSVC has its own `getch` or `_getch` which return at every key press (though you should check out what happens when a non-typing key was pressed, for example PageUp). You can poll before committing to the blocking function with `kbhit` or `_kbhit`. – Weather Vane Sep 02 '17 at 22:37
  • You could look at [Tab completion feature in Unix shell development](https://stackoverflow.com/questions/1046395/tab-completion-feature-in-unix-shell-development), but the answers there aren't as good as the ones here (they only list GNU Readline). – Jonathan Leffler Sep 03 '17 at 04:02

2 Answers2

3

You need the GNU Readline Library. Use the rl_bind_key() function to add a filename-completion processing function whenever the users presses a key ('\t', in your case).

You are in for a world of hurt if you try to roll your own readline style function.

(If you are on Windows.)

Dúthomhas
  • 8,200
  • 2
  • 17
  • 39
  • 1
    @ChronoKitsune ha, just wrote the same, just split seconds after you. But see my answer; libedit is not the only BSD competitor. – Marcus Müller Sep 02 '17 at 22:28
3

Don't reinvent the wheel.

Use what other projects use to build command lines: Libraries that implement that job for you.

Many CLI prompts depend on GNU readline, which I think is fine, if a bit cluttered and heavy. Also, it's GPL, so depends on whether you like that or not.

I'd look into linenoise. It's very lightweight, and if you decide you really want to implement user interface yourself rather than including one or two files, OK, do that, but look at the rather concise reference implementation that seems to be. Caveat: haven't used it myself, so far. The API is pretty simple, though, as can be seen in their example.

A popular alternative is libedit/editline.

Marcus Müller
  • 34,677
  • 4
  • 53
  • 94