[Openmcl-devel] capturing compile errors and warnings

Gary Byers gb at clozure.com
Mon Jun 14 19:53:50 PDT 2010


There isn't a real easy out-of-the-box way to do this, but it's
probably not too hard to cobble something together (and might be an
interesting exercise.)  If you think that this sort of thing is "an
interesting exercise", you'll probably be fascinated by the exercise
called "fixing any bugs or omissions in this code."

Let's say that we want an IDE listener window to become active
whenever a condition object is about to be printed on the listener's
output stream (by WARN or by something that might enter a break loop.)
That concept - activating a window in response to an application-level
event - only makes sense in a windowed environment and the details of what
it means to activate a window depend on the details of that environment;
we want the core part of CCL that prints conditions in these cases to
notify "the application" that a condition's about to be printed and to
let that application-level object decide what (if anything) to do in that
case.

There's some precedent for this and there's a somewhat extensible mechanism
for handling this; unfortunately, much of what's involved here is poorly
documented (if it's documented at all.)   For instance, this incantation:

(advise ccl::%break-message
    (ccl::application-ui-operation ccl::*application*
         :note-break-message *error-output*))

redefines an internal function that's used to report conditions so
that it first calls an undocumented method on an instance of an
undocumented class.  (See ? Interesting ...)  We could also have just
redefined CCL::%BREAK-MESSAGE (which is defined in
"ccl:level-1;l1-readloop-lds.lisp") to call the mysterious
CCL::APPLICATION-UI-OPERATION on entry and rebuilt the lisp and the
IDE, and that change would persist.

The default method on CCL::APPLICATION-UI-OPERATION effectively does
nothing.  (More accurately, it does nothing unless the application
object that it's specialized on has a "UI-OBJECT" associated with it;
if a "ui object" exists, then the generic function
CCL::UI-OBJECT-DO-OPERATION is called on that (arbitrary) object and
CCL::APPLICATION-UI-OPERATION's other arguments.  The first of those
other arguments is conventionally a keyword, which makes it fairly
simple for a "ui object" to use EQL specializers to define responses
to arbitrary events.

In the CCL IDE, the "ui object" associated with the application is the
Cocoa NSApplication instance; there are a handful of
CCL::UI-OBJECT-DO-OPERATION methods defined on NS:NS-APPLICATION near
the beginning of "ccl:cocoa-ide;start.lisp".  Let's add another:

(defmethod ccl::ui-object-do-operation ((o ns::ns-application)
                                         (operation (eql :note-break-message))
                                         &rest args)
   "The first and only arg is a stream to which a condition is about to
    be printed by WARN or ERROR or ... .  If there's a window associated
    with that stream, activate that window."
    ;; Most streams don't have "windows associated with them", but the
    ;; output streams associated with Cocoa listeners do.  Try to see
    ;; if output is ultimately going to such a stream.
    (let* ((stream (car args)))
      (do* ()
           ((not (or (typep stream 'synonym-stream)
                     (typep stream 'two-way-stream))))
        (if (typep stream 'synonym-stream)
          (setq stream (ignore-errors (symbol-value (synonym-stream-symbol stream))))
          (if (typep stream 'two-way-stream)
            (setq stream (two-way-stream-output-stream stream)))))
      (when (typep stream 'gui::cocoa-listener-output-stream)
        (let* ((hemlock-view (slot-value stream 'gui::hemlock-view)))
          (when hemlock-view
            (let* ((pane (hi::hemlock-view-pane hemlock-view)))
               (when (typep pane 'ns:ns-view)
                 (let* ((window (#/window pane)))
                   (#/makeKeyAndOrderFront: window +null-ptr+)))))))))


That basically causes a listener window to pop up whenever the corresponding
thread prints a warning or is about to enter a break loop, regardless of how
that happened (so you could do:

? (compile-large-system)

in a listener, go off and edit some other files, and the listener would
pop up if any warnings/errors occurred during compilation.  There might
be some other, less disruptive approaches somewhere between this behavior
and what currently happens.



On Sun, 13 Jun 2010, John DeSoi wrote:

> I'd like to have the IDE commands Execute Selection and Execute All to bring the listener window to the front when there is an error or warning. I've looked at the sources for a while but I'm not seeing a good way to do that. Any suggestions?
>
>
> _______________________________________________
> Openmcl-devel mailing list
> Openmcl-devel at clozure.com
> http://clozure.com/mailman/listinfo/openmcl-devel
>
>



More information about the Openmcl-devel mailing list