1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00

pyterm: read space after prompt into prompt

Currently, when the prompt is read in `pyterm` the space after it is
ignored for the prompt and the output command just adds its own prompt.
This leads to the next output always having a leading space, see e.g.
this output from `tests/shell` using `RIOT_TERMINAL=pyterm`:

```
make: Entering directory '/home/mlenders/Repositories/RIOT-OS/RIOT2/tests/shell'
/home/mlenders/Repositories/RIOT-OS/RIOT2/dist/tools/pyterm/pyterm -p "/dev/ttyUSB1" -b "500000"
Twisted not available, please install it if you want to use pyterm's JSON capabilities
2021-02-09 14:47:15,071 # Connect to serial port /dev/ttyUSB1
Welcome to pyterm!
Type '/exit' to exit.
bufsize
2021-02-09 14:47:19,712 # bufsize
2021-02-09 14:47:19,712 # 128
> bufsize
2021-02-09 14:47:21,535 #  bufsize
2021-02-09 14:47:21,536 # 128
>
```

While this isn't necessarily a problem in most cases, it becomes a
problem when the prompt is expected and the output of a command is
empty. In that case, the space is added to the empty output, making it
" ", so the prompt output command is never triggered and the prompt is
added to the next command in the log output. To demonstrate I added a
command `empty` to `tests/shell` that just does nothing and deactivated
the command echoing using `CFLAGS=-DCONFIG_SHELL_NO_ECHO=1`:

```
empty
> empty
empty
bufsize
2021-02-09 14:54:33,753 #  > > 128
>
```

This fixes that problem by also reading the assumed space (we already
assume the prompt, so I don't see no harm in that) and if it is not a
space to skip the reading of the next char in the next iteration of the
reader loop.
This commit is contained in:
Martine Lenders 2021-02-09 14:44:29 +01:00
parent 40da80085e
commit 271d1ae3a2
No known key found for this signature in database
GPG Key ID: CCD317364F63286F

View File

@ -688,13 +688,17 @@ class SerCmd(cmd.Cmd):
output = ""
crreceived = False
nlreceived = False
c_already_read = False
while (1):
try:
c = self._read_char()
# try to re-open it with a timeout of 1s otherwise
except (serial.SerialException, ValueError):
self._handle_serial_exception()
continue
# one of the if branches might have read c already
if not c_already_read:
try:
c = self._read_char()
# try to re-open it with a timeout of 1s otherwise
except (serial.SerialException, ValueError):
self._handle_serial_exception()
continue
c_already_read = False
if c == '\r':
if (self.newline == "LFCR" and nlreceived) or (self.newline == "CR"):
self.handle_line(output)
@ -706,6 +710,21 @@ class SerCmd(cmd.Cmd):
elif c == self.serprompt and output == "":
sys.stdout.write('%c ' % self.serprompt)
sys.stdout.flush()
# self.serprompt was read, but a space (that we also printed
# above) may follow. As such, read the next character, but keep
# it for the next iteration in case it is not a space.
# If we don't do this, the space from the prompt will be
# prepended to the next output, causing the next prompt on empty
# output potentially to be ignored, since `output` will be " "
try:
c = self._read_char()
# try to re-open it with a timeout of 1s otherwise
except (serial.SerialException, ValueError):
self._handle_serial_exception()
continue
if c != ' ': # not a space?
# then use `c` in the next iteration
c_already_read = True
else:
output += c