Seeking guidance on fixing an IOHandlerEditLine Hide/Refresh problem

[Caveat: This is a minor issue, but it’s annoying to me, so I’d like to at least explore how to fix it properly before giving up.]

So my standard use of lldb is inside of gud-mode in emacs. In that mode, I believe line editing is disabled (the output of lldb is a dumb terminal that emacs wraps). As a result, IOHandlerEditLine::Hide and Refresh are not balanced; Hide() does nothing, and Refresh() re-prints the prompt.

The result of this is that when I’m debugging an inferior that has a lot of output, I get many copies of the (lldb) prompt interwoven with the output. I’ve traced this behavior to Debugger::HandleProcessEvent() being called repeatedly with event_type Process::eBroadcastBitSTDOUT. In such a situation, it calls HideTopIOHandler(), copies the output out, and then calls RefreshTopIOHandler().

The behavior that I personally think would be ideal in this configuration would be for the prompt only to be refreshed if an inferior event other than stdout or stderr occurs. And I can code that in Debugger::HandleProcessEvent() pretty easily by only calling refresh if some other event is occurs, but that’s clearly the wrong architectural choice (because it breaks the Hide/Refresh contract on IOHandler). Maybe adding an argument to RefreshTopIOHandler indicating if the refresh was requested because anything other than output was copied? I’m almost tempted to just pass in the event type, but it doesn’t really make sense that IOHandlers know about the Process broadcast constants.

Anyone have any thoughts? (Including “This is minor and fixing it would be a hassle; live with it” :-})

– Randy

One option would be to redirect stdin/out/err when you launch your process:

(lldb) process launch --stdin /path/to/stdin.txt --stdout /path/to/stdout.txt --stderr /path/to/stderr.txt

Not sure if you could make a new emacs buffer that could hook up the in/out/err file handles to the inferior process? If you do that, then no eBroadcastBitSTDOUT will be sent!

I don't know much about the emacs, but it seems like this might be nice to get all of your process input/output in a separate window?

Greg

One option would be to redirect stdin/out/err when you launch your process:

(lldb) process launch --stdin /path/to/stdin.txt --stdout
/path/to/stdout.txt --stderr /path/to/stderr.txt

Not sure if you could make a new emacs buffer that could hook up the
in/out/err file handles to the inferior process? If you do that, then no
eBroadcastBitSTDOUT will be sent!

I don't know much about the emacs, but it seems like this might be nice to
get all of your process input/output in a separate window?

Hmm. Yes, that's probably the right choice. it doesn't fit with how emacs
currently wraps its debuggers, but that wrapping is sort of half IDE/half
CLI, rather than one or the other (it puts the debugger CLI in what's
effectively a shell window, and eavesdrops on communications to keep the
source window pointing at the right code). This would be a better user
experience, and would be the right choice for a "real" IDE, so it's likely
the right answer as far as LLDB is concerned.

Thanks for the idea!

-- Randy

Hey Randy,

If you end up sharing what you do with emacs, I’d love to have a look at some point. (I’ve spent a good part of my life in emacs :slight_smile: )

Hey Randy,

If you end up sharing what you do with emacs, I'd love to have a look at
some point. (I've spent a good part of my life in emacs :slight_smile: )

I'm happy to share with individuals currently (I'll send you a separate
email). I'm holding off on upstreaming/general distribution partially for
soak time and partially because I'm not sure what the best way to upstream
is (upstream->lldb ==> breakage as emacs moves, upstream->emacs ==> same
(though probably not as bad), "best" answer is refactoring gud.el so that
there's a tight interface to underlying debuggers and upstreaming only lldb
specific code to lld). So I want to be comfortable that it's actually of
general value before going through the hassle.

-- Randy

You might find the various package distribution mechanisms to be interesting for emacs. I use package.el with:

(require 'package)
(add-to-list 'package-archives
'(“melpa” . “http://melpa.milkbox.net/packages/”))
(add-to-list 'package-archives
'(“org” . “http://orgmode.org/elpa/”))

The first one is the main one I use (tends to keep things more up to date than other package sites, but might be more bleeding edge). I’ve never distributed anything through it, but as a consumer I sure like the package manager mechanism vs. the crazy things I’ve done over the last 25 years to keep my emacs setup. That might be an interesting place to investigate.