[Openmcl-devel] format to a hemlock view's buffer
Arthur Cater
arthur.cater at ucd.ie
Fri Feb 3 03:50:53 PST 2012
Thank you Gary for responding, I appreciate the help.
The test case code attached here is quite small, 42 lines, see below.
Since everything it does is done inside gui::execute-in-gui I have removed
the redefinitions of stream-write-char and stream-write-string that ensured this.
I have taken code from handle-hemlock-event that seems to me to cover
the protocol issues you mentioned, and - with some reordering of bindings -
encapsulated it in the with-hemlock-protocol macro. Without success:
still, a mouseclick moves the visible cursor but a subsequent arrowkey
reveals the buffer-point is still at the end of the inserted text.
Arthur
-------------- next part --------------
A non-text attachment was scrubbed...
Name: unclickable.lisp
Type: application/octet-stream
Size: 2291 bytes
Desc: not available
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20120203/7264ef48/attachment.obj>
-------------- next part --------------
(in-package hemlock)
(defmacro with-hemlock-protocol (streamexpr &rest actions)
(let ((stream (gensym)) (mark (gensym)) (view (gensym)) (text-buffer (gensym)))
`(ccl::with-standard-abort-handling "Abort editor event handling"
(let ((,stream ,streamexpr) ,mark)
(if (and (typep ,stream 'hi::hemlock-output-stream)
(setq ,mark (hi::hemlock-output-stream-mark ,stream)))
(let* ((,text-buffer (hi::line-buffer (hi::mark-line ,mark)))
(hi::*current-buffer* ,text-buffer)
(,view (gui::front-view-for-buffer hi::*current-buffer*))
(hi::*current-view* ,view)
(hi::*next-view-start* nil) ;; gets set by scrolling commands
(mod (hi::buffer-modification-state ,text-buffer)))
(hi::modifying-buffer-storage (hi::*current-buffer*)
(restart-case
(handler-bind ((error #'(lambda (c)
(hi::lisp-error-error-handler c :debug-p t))))
, at actions)
(hi::exit-event-handler () :report "Exit from hemlock event handler")))
;; Update display
(if hi::*next-view-start*
(destructuring-bind (how . where) hi::*next-view-start*
(hemlock-ext:scroll-view ,view how where))
(unless (equal mod (hi::buffer-modification-state ,text-buffer))
;; Modified buffer, make sure user sees what happened
(hemlock-ext:ensure-selection-visible ,view)))
(hi::update-echo-area-after-command ,view))
(error "~s is not a hemlock-output-stream" ,stream))))))
(defun cl-user::myview (nlines)
(gui::execute-in-gui ; Makes the view
#'(lambda nil
(let* ((ccl::*default-file-character-encoding* :utf-8)
(view (gui::find-or-make-hemlock-view nil))
(buffer (hemlock-view-buffer view))
(stream (hi:make-hemlock-output-stream (buffer-start-mark buffer) :none)))
; All possible values {:none, :line, :full} apparently have the same effect
(with-hemlock-protocol stream
(dotimes (num nlines) (format stream "Line ~a is here~%" num)))))))
(cl-user::myview 7)
On 3 Feb 2012, at 02:11, Gary Byers wrote:
> Sorry for not responding earlier (and I still haven't looked at your
> test case in any detail.)
>
> A Hemlock buffer in the IDE is (usually/always/almost always) associated
> with a Cocoa text view; from the point of view of the text view, the
> Hemlock buffer implements the view's text storage.
>
> Modifying an NSTextStorage object safely and sanely requires that a certain protocol be observed; that protocol involves telling the text
> system that editing (if the storage object) is in progress, informing
> it of what ranges of text are affected by insertions/deletions/etc,
> and telling the text system that a sequence of editing operations has
> been completed and the view should redisplay affected areas.
>
> When a Hemlock command runs (usually in response to some key event),
> it (a) runs on the main Cocoa event thread and (b) observes this protocol;
> it can call HI::INSERT-CHARACTER and HI::INSERT-STRING (or have FORMAT
> do that), and these things mean that modification on the buffer/textstorage
> is synchronised with redisplay of the containing view. Nothing really
> enforces the first constraint (that everything's happening on a single
> thread) except for the fact that trying to modify the buffer from some
> other thread will probably lead to display and other problems.)
>
> It'd be nice if there was some protocol that allowed arbitrary code
> (running in an arbitrary thread) to modify Hemlock buffers in thread-safe
> ways and to ensure that those modifications were made in accordance with
> Cocoa constraints. That protocol doesn't exist.
>
> Like I said, I haven't really looked at this but I suspect you'll find
> that FORMAT modified the buffer as expected but (a) the text view doesn't
> know that and (b) it's possible that other code running concurrently
> was also modifying the buffer in some ways while FORMAT was.
>
> On Thu, 2 Feb 2012, Arthur Cater wrote:
>
>> Thanks Glen.
>>
>> I've never looked at the innards of Format, but I assumed it bottoms out in calls
>> to stream-write-char, stream-write-string, and perhaps stream-terpri.
>> And these all turn into hi::insert-character and hi::insert-string.
>> So I'm puzzled about what does foul up the insertion point.
>>
>> Arthur
>>
>>
>> On 2 Feb 2012, at 09:49, Glen Foy wrote:
>>
>>> Arthur,
>>>
>>> If you can't find a solution to the stream/format approach (which I like), you might try using hi::insert-string.
>>>
>>> It accepts a :charprops parameter and will not foul up the insertion point.
>>>
>>> -- Glen
>>>
>>>
>>> On Feb 1, 2012, at 10:36 AM, Arthur Cater wrote:
>>>
>>>> I am having trouble with cursor position in a programmatic Hemlock view.
>>>> The attached (also enclosed) code makes a Hemlock view, creates a stream
>>>> to write to it, and writes a few lines using format.
>>>
>>
>> _______________________________________________
>> Openmcl-devel mailing list
>> Openmcl-devel at clozure.com
>> http://clozure.com/mailman/listinfo/openmcl-devel
>>
>>
More information about the Openmcl-devel
mailing list