Tony has a couple of nice blogs on his adventures in this area...
That's really only the internal design of the console.device. FYI, ViNCEd works completely different from that and has two internal representations of lines: A "packed" line where each line is broken up into "words" that share the same attributes, with blanks in between, and an unpacked version with a one-byte glyph and a two-byte attribute per character in the line. Whenever the cursor enters a line, this line is unpacked, the user makes edits, and when the cursor leaves the line, it is packed again.
The internal representation is all fine, but the problem is how the console interacts with the shell. ViNCed somehow "hijacks" the CLI structure of the I/O streams that reach the handler, and from that "guesses" (it's a bit better than this, but let's make it simple) what the corresponding CLI is, from there figures out what the path is, and from there runs the TAB-expansion, and from there places the expansion back into the window. Actually, a separate side-thread is responsible for that.
It works, but the bad part about is the lack of isolation. Essentially, the console has to mess with data structures (the CLI) it should really not care about. The CLI structure is frozen, so nothing bad can happen, but it's still not how it is supposed to work. The shell should care about its own structures, and do the expansion, and the console should inform the shell when the user needs an expansion.
On the ViNCEd side (not the "ROM console") everything is there to support such an improved operation, but from the Shell side it is not.