Miscellaneous comments regarding this code
Clone this wiki locally
Some of the important changes — at least for me. These make a big difference in my ability to write, develop and maintain code.
First, I now have load-relative and require-relative functions which don’t require me fiddling with load-path to do the internal linking of the program. Using Emacs load-path variable may be okay for finding an initial Emacs package to load, but is clumsy, cumbersome and unreliable as a way for the package to find its internal sub-modules.
Second, I have switched unit testing from elk-test.el to emacs-test-simple .
By removing gud.el, a lot of the globalness has gone away.
To process debugger output, the comint mode hook now uses the marks that comint sets in the process or command buffer. Functions have been added for processing a marked region. So to test you can now mark a region and call a function that the hook calls. Or if you want to just pass a string instead of a marked region that can be done too.
Some of this code extends from the Emacs code for rdebug. What was called “secondary” windows (or buffers) there, are called “source-code” windows (or buffers) here. The buffer that interacts with the debugger process is called the “command buffer”. The command buffer is where most of the debugging state information is kept, which in the past was global. Source-code buffers are another place where debugging information may be saved, but this is more related to source-code information for that buffer only. There is a buffer field inside the source-code structure which gets you back to the corresponding command buffer. (In the future, there should be a provision for storing more than one command buffer, since it is possible for the source-code file to be participating in two different debug sessions. For now, that is unneeded complexity.)
Over time, I may put more specialized information in the other buffers such as for breakpoint info, local variables names/values, etc. For now though, these are the only two places I need.
A key change over what went before is that I am making more use of the programming language Lisp, rather than dumping text in buffer(s) and scanning and parsing that. A location is now a Lisp structure that contains a source file, source line, a mark object in both the command buffer and a source buffer. I keep a ring of locations so that you can move back in time over the course of executing the code. The last 3 positions are marked in the fringe as the positions go farther back the color fades.
Most recently I just got around to looking at short-key mode of rdebug. The thing I didn’t like about that was its globalness throughout all debugging sessions rather than per debugging instance. So what I’m doing now is saving whether short-key is on or off inside the debugger command buffer structure. From the source-code buffer, of course, you can change short-key mode, but that (in addition to changing its short-key-mode state) is registering the state back in the command buffer. As we move along in debugging, the buffers of source code locations that we stop in are forced to be in the state that the command buffer has registered. As a result, I don’t think I need an “internal short-key” mode in addition to the “short-key” mode as is done in rdebug.
Finally there is a change (perhaps) in how the windows are handled. What is there now isn’t as fully developed as what you had. However I think I have a better handle on the lower-level routines. In the past, at least in my coding of the rewrite, I was lax about whether having functions not switch buffers or windows. Now, I make sure to constrain all of this to few places; no non-window function permanently switches windows. Buffer switching is likewise limited too. Other functions which may need to work with source or command buffers/windows may temporarily switch them such as to update the fringe or point; but they must make sure that the current buffer or selected window is the initial value on return.
The idea is that at the end all buffer information and position information is set up, and towards the end a decision is then made about what the overall layout should look like and a single routine is responsible for setting the final window layout and buffer placement within that.