reddit / emacs
a REPL over a serial port, utilizing MicroPython with Emacs?
SlowValue · 2022-10-19 22:03
MicroPython runs on some embedded systems. It provides a Python REPL through the serial port (e.g. `/dev/ttyACM0`). One can use it through `(serial-term "/dev/ttyACM0" 9600)` from within Emacs.
On the other hand `python-mode` provides some functionality (like `python-shell-send-buffer` or `python-shell-send-defun`) to interact with an active, locally running python3 REPL.
I'd like to be able to send Python code from a Python-file buffer directly (without me copying and pasting) to the MicroPython REPL.
Any idea how to achieve that?
ieure · 2022-10-20 02:20
You can't do that with `serial-term`, because it's based on `term.el`, and `inferior-python-mode` is based on `comint`.
You'll need to build your own Emacs command that calls `make-serial-process` to set up the serial comms, then enables `inferior-python-mode`.
JDRiverRun · 2022-10-20 03:53
You can probably get pretty far configuring `mpremote connect /dev/ttyACM0 repl` as your inferior python shell command. I believe I have tried that with success, after tuning some comint variables like process-echoes, etc.
inferior-python-mode will need some heavy config tweaking, since by default it attempts to save various local temp files with lots of completion and other helper code, and have python exec them (which obviously won't work). See the python-shell-eval-\* variables.
SlowValue · 2022-10-20 09:11
Thanks for pointing to `mpremote`. While using mpremote from a terminal works, I could not yet get it communicating within emacs (there is no prompt).
I'm a noob regarding comint. Do you remember by any chance more about this mentioned config tweaking?
SlowValue · 2022-10-20 09:24
Thanks for clarifying that serial-term won't work, so I can discard that direction. I already tried `(make-serial-process :port "/dev/ttyACM0" :speed 9600 :buffer "*Python*")` and then enabling comint-mode. in order to get it communicating, but I guess there is some more setup required.
Any idea what? (I'm sort of clueless regarding comint, yet)
JDRiverRun · 2022-10-20 15:53
Sorry, I can't find anything, but I know I got this working. First see if you can even make a basic comint shell for it. Eval something like this in \*scratch\*:
`(make-comint "MPREMOTE" "mpremote" nil "connect" "/dev/ttyACM0" "repl")`
inferior-python-mode is not going to do much for you, since the way it tries to send regions/functions/files requires compiling helper code and interacting with temporary files on your system. But it would be pretty simple to overload those commands to paste the region in using micropython's simple [paste-mode](https://docs.micropython.org/en/latest/reference/repl.html#paste-mode) (i.e. wrapping in C-e and C-d).
SlowValue · 2022-10-20 20:39
Thanks for having a look, I found [your old thread](https://old.reddit.com/r/emacs/comments/pesnhv/comint_interaction_with_promptbased_command_over/) but there is not much info.
My current problem is, I can't get a prompt from `mpremote` and it seems, that the mpremote process does not receive any newline characters from Emacs.
What i did until now:
Setup the comint buffer
(make-comint-in-buffer "mpremote" "*Python*" "mpremote" nil
"resume" "repl" "--capture" "foo.log")
I get a buffer with the following content
Connected to MicroPython at /dev/ttyACM0
Use Ctrl-] to exit this shell
Capturing session to file "foo.log"
Then I input `print("Hello")` `ENTER` and `print("world")` `ENTER`, the buffer then displays the following:
print("hello")
print("hello")
print("world")
print("world")
Having a look into file `foo.log` shows
print("hello")print("world")
So it received my input but it did not receive the newline character (ENTER).
Does that make any sense?
*Notes*:
I already played with `comint-input-sender-no-newline nil` and other comint variables.
Doing all the comint steps from above with `(make-com... "python3" ... "-i")` works as expected. Using `mpremote` on a ordinary terminal outside of Emacs also works as expected.
Enabling `term-char-mode` inside the mpremote comint buffer, "promotes" it to an terminal and I could use it, but it has all the disadvantages of an terminal inside emacs.
JDRiverRun · 2022-10-20 20:53
Well that's funny. Looks like I already tried mpremote and switched to the older rshell. A standard impedance mismatch between a given command line tool and comint is whether the tool expects to have rich access to control-characters as they are entered (as they would in a real terminal), or whether they are happy enough with "line at a time". You can always check if the newline is being sent (via `comint-simple-send`) by M-x trace-function'ing it. I suspect it is (at least if no-newline is nil). In fact, you [can see mpremote](https://github.com/micropython/micropython/blob/4c252ae067a4798fe11c2ce56a9734c1e64846a8/tools/mpremote/mpremote/main.py#L312) handling newlines specially; you may be able to switch this to a \`\\r\` return char instead and make progress.
Look at `comint-process-echoes` to fix your duplicated input.
BTW, is this MP device networked? A while ago I started a mode I called micropython.el which would connect to MP over a network socket and could run in TERM (terminal), EXEC (execute Python commands even when the terminal is blocked), or STOR (file transfer) mode, all across the same connection. It requires a tiny network server to be run on the MP device (sort of like utelnet and uftpd combined). Only 1/4 finished, but if you're looking for a project...
SlowValue · 2022-10-20 22:10
You are right, mpremote (or rather the MicroPython, I suspect) needs a `\r` to process its input.
For anyone who reads this: `M-: (comint-send-string (get-process "mpremote") "print(\"hello\")\r")`. does something inside the comint buffer and gets you a fresh promt.
So I need to modify `comint-simple-send`, so that it sends a `\r` instead of an `\n`. And then put this function name into variable `comint-input-sender`.
Thank you for your help solving this puzzle!
Yes my MP device has WLan. Your mode sounds nice, maybe I can contribute a thing or two. But beware, I'm very new to MicroPython and to Python. I should figure out the basics first e.g. how to get this WLan stuff operating. Also I'm curious about [uLisp](http://www.ulisp.com/). :)