mu icon indicating copy to clipboard operation
mu copied to clipboard

ctrl-C in REPL disabled when switching back and forth with the code panel

Open Neradoc opened this issue 4 years ago • 15 comments

  • MacOS Catalina
  • Mu beta 4
  • QT PY 2040 running CircuitPython 6.2.0 or latest
  • also other Circuitpython boards

Running a simple script that prints "hello" every seconds.

  • Open Mu
  • open the serial panel (click on serial)
  • ctrl-C ctrl-D behaves as expected
  • click back and forth between the code and the serial panels (once or twice) (and I mean in the window, not the button)
  • ctrl-C stops working (the board keeps outputting "hello")
  • quit Mu
  • connect to the board with tio
  • ctrl-C still does not work
  • stop the code by adding an error (or pressing a button)
  • a few >>> are printed, as if a buffer of the ctrl-Cs were unloaded at once

Here is the code.py I tested with:

import board
import time
from digitalio import DigitalInOut,Pull

button = DigitalInOut(board.BUTTON)
button.switch_to_input(Pull.UP)

while button.value:
	print("hello")
	time.sleep(1)

Neradoc avatar Apr 25 '21 13:04 Neradoc

This may be a CircuitPython sleep bug. Try this with some other terminal program to start with (not using Mu at all). Viz. https://github.com/adafruit/circuitpython/issues/4658

dhalbert avatar Apr 25 '21 14:04 dhalbert

It's really triggered every time by clicking in Mu, and I get the same behavior without the print and the sleep (just pass), so I don't know if it's a different issue, or if there's something that Mu does when clicking the window that triggers it.

Neradoc avatar Apr 25 '21 17:04 Neradoc

Thanks for the report @Neradoc, can you trigger the same issue only using tio?

carlosperate avatar Apr 26 '21 18:04 carlosperate

Finally looked at the Mu code and I have been able to solve it by commenting out the following lines, which are run whenever you click in the REPL pane.

https://github.com/mu-editor/mu/blob/2b20da24e5219002fe19781509fa8665a9842464/mu/interface/panes.py#L318-L323

So I was able to reproduce the issue with:

serial_port = "/dev/cu.usbmodem144443131"
import serial
VT100_RIGHT = b"\x1B[C"
channel = serial.Serial(serial_port)
channel.write(VT100_RIGHT*50)
channel.close()

So, it's not a Mu issue.

Neradoc avatar Apr 30 '21 12:04 Neradoc

It looks like this is a device specific issue, so I'll close this, but please feel free to reopen if it was an issue in Mu. Thanks everyone!

carlosperate avatar Dec 17 '21 19:12 carlosperate

Hey, is it ok to reopen ? This keeps being a problem, even on the pico, as you can see in https://github.com/adafruit/circuitpython/issues/7183

As it stands right now in a normal use scenario, say:

  • you open the serial panel to see the output while editing code.py and saving.
  • the code is printing stuff so it fills the serial screen.
  • you click in the panel so that you can send ctrl-C.

Mu sends "move left" (3 characters \x1b[D) as many times as there are characters between where you clicked and the bottom of the panel, which might be hundreds, filling the USB buffer. At that point the data stops being sent to the board by the computer (which might still queue more characters). Since we don't want to discard serial data, as this might actually end up being normal, just a big buffer being sent, we can't detect ctrl-C when that happens.

I think we should discuss if moving the cursor with a click is a useful feature at all or if we can find a middle ground where Mu ignores clicks when:

  • the serial panel was not active (you were typing in code.py).
  • the last line doesn't start with >>> or ... (which usually means we are not in the REPL).
  • the line clicked is not the last line. (I don't think the REPL can back up the cursor more than one line anyway).

The first one might not even be necessary with the other two. Am I missing something ? Is there another use of that cursor moving feature ? Maybe outside of Circuitpython ?

Neradoc avatar Dec 09 '22 01:12 Neradoc

Another non-upward-compatible alternative is to eliminate clicking as a way of moving the cursor in the Serial window, and just rely on arrow-key movements. I was unaware that one could click in that window to move the cursor until @Neradoc told me about it. I found it surprising, since I expected it to act like a typical terminal window where clicking is a "meta" operation that does not generate usually generate output.

dhalbert avatar Dec 09 '22 01:12 dhalbert

+1 on that this cursor movement is an unexpected feature and not part of most typical terminal windows and behaviours.

How about making this feature optional, and off-by-default when Mu is in CircuitPython mode? (or does e.g., MicroPython-powered devices suffer from the same problem?) Advanced users could still enable it in the settings if they know what they are doing -- at least novice users get a more reliable and working system.

Kriechi avatar Dec 09 '22 02:12 Kriechi

Hey, is it ok to reopen ?

Of course! I closed this one assuming it was device specific, but as you've clarified, this is directly related to the cursor position commands Mu sends.

I think we should discuss if moving the cursor with a click is a useful feature at all

Another non-upward-compatible alternative is to eliminate clicking as a way of moving the cursor in the Serial window, and just rely on arrow-key movements

+1 on that this cursor movement is an unexpected feature and not part of most typical terminal windows and behaviours.

This feature was added because we saw in workshops that begginers (of all ages, but it was specially important with users that struggled a bit more with the keyboard) were constaly clicking in the middle of a REPL command to fix typos before sending them. In those occassions it was very confusing when the newly typed characters ended up at the end of the terminal output. Even if we lock/remove cursor placement with the mouse, when doing these workshops it was clear that users these days expect mouse controls to work in this regard. So, at least from my point of view, it's important to maintain this feature.

or if we can find a middle ground where Mu ignores clicks when:

  • the serial panel was not active (you were typing in code.py).

I think a middle ground would be good, and I like this suggestion. My guess is that it should be relatively easy to ignore the click position when the serial panel is not active and then a click only activates the panel rather than change the cursor position. That should aliviate the majority of the problem, specially if we can also make sure the click is ignored if the happens when the window is out of focus, as that might also be common when switching between windows.

  • the last line doesn't start with >>> or ... (which usually means we are not in the REPL).

For this one, I'm a bit hesitant to add more processing of the serial data within Mu. This is because the current implementation is not very efficient and adding more code there will likely reduce performance. Is relatively easy to "flood" Mu and make it unresponsive when it receives a lot of serial data, so I'd like to keep this area as lean as possible.

  • the line clicked is not the last line. (I don't think the REPL can back up the cursor more than one line anyway).

I thought that's the way it currently works?


@ntoll do you have any thoughts, suggestions or insights?

carlosperate avatar Dec 12 '22 18:12 carlosperate

CircuitPython also recently added a break signal: https://github.com/adafruit/circuitpython/pull/7227 supporting this in Mu would be another improvement for the same problem of Ctrl-C being broken sometimes.

Kriechi avatar Dec 12 '22 19:12 Kriechi

  • the line clicked is not the last line. (I don't think the REPL can back up the cursor more than one line anyway).

I thought that's the way it currently works?

I'm using a test code.py that sends back the characters that it received.

import usb_cdc
while True:
    data = b""
    while num := usb_cdc.console.in_waiting:
        data += usb_cdc.console.read(num)
    if data:
        print(f"> {len(data)} chars: {data[:16]}{'...'*(len(data)>16)}")

This is after hitting return in the REPL a few times to clean the screen, then ctrl-D, then clicking a few times in the center of the serial panel (stretched to around 16 lines).

>>> 

Auto-reload is on. Simply save files over USB to run them or enter REPL to disable.
code.py output:
> 381 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 528 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 675 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 822 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 969 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 576 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 540 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 1281 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 1302 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 1311 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 1024 chars: b'\x1b[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b'...
> 290 chars: b'[D\x1b[D\x1b[D\x1b[D\x1b[D\x1b['...

Neradoc avatar Dec 15 '22 16:12 Neradoc

OK. Happy "Mu" year folks... (sorry).

Just been looking through this and I think #2373 is a good enough / pragmatic solution. I'll merge and let's see if this issue goes quiet.

Thank you for contributing.

ntoll avatar Jan 09 '23 19:01 ntoll

We are currently running Mu 1.2.0 (official release) and have the issue almost all of the time - even when avoiding (as much as possible) switching between code and terminal.

No issues were observed when using Putty (or Kitty).

I see there is a 1.2.1 milestone plan from 11 months ago. We are planning a workshop series and want to use Mu.

bradanlane avatar Dec 18 '23 15:12 bradanlane

MU version 1.0.2 works just fine with Ctrl+c. I am using a RP2040 prop-maker. Mu Version 1.2.0 does not work after about 10 to 20 seconds.

Electro-Mike avatar Apr 04 '24 00:04 Electro-Mike

Any progress on this? I had really really frustrating experience with it today trying to teach an Upward Bound class. Right before class was to start, my Windoze 11 running Mu 1.2.0 started doing this. I downgraded to Mu 1.1.1 and still had issues (also started seeing some weird "9.0.5" messages in the Repl window, but it would not respond or show any print output from the code.py -- running a Pico w 9.0.5OS. I tried the same rPi Pico on a rPi 4B and it worked just fine.... although I couldnt use that for class teaching.

MauiJerry avatar Jun 26 '24 04:06 MauiJerry