On Thursday 14 May 2009 21:59, Rob Landley wrote: > > > However, if your shell prompt didn't start at the left edge of the screen > > > (which happens surprisingly often), the resulting line editing is > > > completely horked once you go past the right edge of the screen. > > > (Command history becomes a lot less fun to use, too.) > > > > > > It's easy enough to fix once you know what the problem is and decide to > > > address it. We just haven't yet... > > > > How to address it? > > Query the current cursor position at the start of an interactive shell > prompt, > which is very similar to querying the width and height o the screen.
Yes, I know that this is achieved with the same ESC sequence. My worry is that if the response is processed asyncronously (looks like it's more sane way to do that), then it does not know what that response means. > The ansi escape mentioned previously consists of "save position", "jump to > lower right", "query current cursor position", "restore saved position". If > you just send the query without the save/jump/restore, you should get current > cursor position back. I got that. > The shell's command line editing and vi already have escape parsing logic, so > it's relatively easy to fix this in two parts there. (The escape reply > should always come in as a single unit without interspersed characters, we > just don't know _when_ we'll get it, or how long the delay might be. But > there could always be unrelated data before/after it, coming in > asynchronously.) > > A more general fix is to extend get_terminal_width_height() with the ANSI > escape and parsing code so that it tries harder when it can't get useful info > from the tty querying ioctl. But this is fiddlier, because it can't always > blindly output the sequence and hope for the best. > > For example, the "ls" command calls get_terminal_width_height() but when > running that in a pipe adding spurious escape output isn't a good thing. > However, most of that could be cleaned up by grabbing the code from the tty > applet to identify our controlling tty (and whether we have one) and write > the probe string directly to the tty instead of to stdout, and simply not > probe if we haven't got a tty. (I just checked and the tty command does > output /dev/ttyS0 or /dev/console when it's your controlling tty, even though > neither knows your screen size. The only time we _don't_ have a tty is when > we're in a pipe.) > > I suspect ls already does a little of this sort of thing for colors, but I > haven't checked... > > > Try running eval `resize`. Does it (a) work at all? and > > (b) does it set LINES and COLUMNS? > > Setting columns and lines is a good thing, but A) it's a separate issue from > detecting cursor position, B) I think it's something the shell should do > automatically. (It already does so in the pty case, just not for serial > consoles.) > > The more I think about it, the more the general fix to > get_terminal_width_height() seems like the way to go, because there are > actually _three_ race conditions with querying cursor position. > > The first is of course that the user can press a key at any time, so the > escape sequence reply you get may not be the first data in the input. > Robustifying get_terminal_width_height() means adding at least an optional > way to receive back all the other input that came in before the escape reply, > so you can process it. (Note that this could include other unrelated > escapes, like "cursor up" for command history, so we can't just stop at the > first escape sequence, it has to be the _right_ one. Again, there's existing > escape parsing logic in busybox...) > > The second race condition is that the standard vi or shell escape parsing > logic will print characters out as it receives them, and this moves the > cursor position. So when we _do_ get the cursor position escape back, > presumably that's the cursor position at the point in the data stream > _before_ we printed the extra characters that were pending in our input... > but we've lost that context. Seems like it's best not to print any output > between sending the probe and receiving the reply (or timing out waiting for > the reply), and then we can parse the other input afterwards. > > The third race condition is that if you're querying both screen size _and_ > cursor position, you get back the same reply string and it means two > different things depending on context. (This is only a race condition if you > alter the vi/shell escape parsing logic and respond to it asynchornously in a > different context than the probe was sent from. Yeah you could have a global > variable indicate which one you were waiting for but that's ugly.) Exactly. I propose to try a simple solution first: * defeat "echo -n blabla" by outputting \r before the prompt. Do we really care about these cases when there is an unfinished line of output? * make read_key listen to ESC"[NNN;NNNR" sequence and return its values * if neither $LINES/$COLUMNS are set nor ioctl(TIOCGWINSZ) returns useful data, print ESC"7" ESC"[r" ESC"[9999;9999H" ESC"[6n" ESC"8" in order to retrieve terminal's size, and whenever read_key does detect that, use this info for proper linewrapping in line editing. First snag I hit is that line editing does not yet use read_key, it has another (and buggy) implementation. Fixing that. Is the above plan good? -- vda _______________________________________________ busybox mailing list [email protected] http://lists.busybox.net/mailman/listinfo/busybox
