|
|||
|
Hi,
I'm writing a newbie friendly IDE and have some basics up and running but have hit my first problem: how to send user input back to Lisp. If the user evaluates something like: (read-line) I'd like to activate an 'edit control' to type input (I'm using LTk but I don't think any of this is library specific). My attempts so far have been rather naive: 1) bind *standard-input* directly to a text widget. This fails, I believe, because I have no way of stopping to prompt the user for input once the eval is reading the above code. So *standard-input* simply hits eof before anyone has a chance to input anything. 2) bind *standard-input* to a stream returning function. I seem to run into a typing error here. What I actually want to do is: every time input is requested, _run_ my function (i.e. pop up a modal window prompting the user for text, marshal this using make-string-input-stream and return the stream with the text in it). I'm not sure if this is possible (i.e. can I bind something that is actually evaluated each time to *standard-input* or am I being ridiculous?). I guess I was thinking of events / call-backs but as I read this back, it does seem like nonsense... Or is there an entirely different approach I could use? As I mentioned in a previous thread, I'm not using Swank as I think it will be too much for me to digest at this point in my Lisp learning but if all of this is impossible then I guess I have no choice but to put this project on hold for a while. This would be a shame though as I'm already using the program to program with (for all but user input and debugging anyway...). Many thanks. Phil |
|
|
||||
|
||||
|
|
|
|||
|
philip.armitage@gmail.com writes:
> My attempts so far have been rather naive: > > 1) bind *standard-input* directly to a text widget. This fails, I > believe, because I have no way of stopping to prompt the user for input > once the eval is reading the above code. So *standard-input* simply > hits eof before anyone has a chance to input anything. > > 2) bind *standard-input* to a stream returning function. I seem to run > into a typing error here. What I actually want to do is: every time > input is requested, _run_ my function (i.e. pop up a modal window > prompting the user for text, marshal this using > make-string-input-stream and return the stream with the text in it). > I'm not sure if this is possible (i.e. can I bind something that is > actually evaluated each time to *standard-input* or am I being > ridiculous?). I guess I was thinking of events / call-backs but as I > read this back, it does seem like nonsense... > > Or is there an entirely different approach I could use? *STANDARD-INPUT* has to be bound to some kind of stream; the standard functions won't know what to do if it's a function or an Ltk widget. The most straightforward way to achieve what you want is to use Gray streams, if your implementation supports them. Gray streams let you define streams as CLOS classes. You could perhaps define a class that inherits both from the Ltk text widget class and also implements an input stream. Then you *can* bind *STANDARD-INPUT* directly to the text widget. |
|
|||
|
On Sun, 03 Dec 2006 02:08:34 +0100, <philip.armitage@gmail.com> wrote:
> > 2) bind *standard-input* to a stream returning function. I seem to run > into a typing error here. What I actually want to do is: every time > input is requested, _run_ my function (i.e. pop up a modal window > prompting the user for text, marshal this using > make-string-input-stream and return the stream with the text in it). > I'm not sure if this is possible (i.e. can I bind something that is > actually evaluated each time to *standard-input* or am I being > ridiculous?). I guess I was thinking of events / call-backs but as I > read this back, it does seem like nonsense... > For this approach I suggest you look at the source code for Swank the Lisp spesific part of SLIME that sets up the socket interface. You could use a pipe also or even shared memory. Some systems allow all three (MS SQL) though either one would do. Event callback sounds like nonsense. Send a command and retrieve the output in a shell. By the way are you aware that there is a Lisp interface plugin for Eclipse? -- Using Opera's revolutionary e-mail client: http://www.opera.com/mail/ |
|
|||
|
philip.armitage@gmail.com writes:
> Hi, > > I'm writing a newbie friendly IDE and have some basics up and running > but have hit my first problem: how to send user input back to Lisp. If > the user evaluates something like: > > (read-line) > > I'd like to activate an 'edit control' to type input (I'm using LTk but > I don't think any of this is library specific). > > My attempts so far have been rather naive: > > 1) bind *standard-input* directly to a text widget. This fails, I > believe, because I have no way of stopping to prompt the user for input > once the eval is reading the above code. So *standard-input* simply > hits eof before anyone has a chance to input anything. > > 2) bind *standard-input* to a stream returning function. I seem to run > into a typing error here. What I actually want to do is: every time > input is requested, _run_ my function (i.e. pop up a modal window > prompting the user for text, marshal this using > make-string-input-stream and return the stream with the text in it). > I'm not sure if this is possible (i.e. can I bind something that is > actually evaluated each time to *standard-input* or am I being > ridiculous?). I guess I was thinking of events / call-backs but as I > read this back, it does seem like nonsense... > > Or is there an entirely different approach I could use? > > As I mentioned in a previous thread, I'm not using Swank as I think it > will be too much for me to digest at this point in my Lisp learning but > if all of this is impossible then I guess I have no choice but to put > this project on hold for a while. This would be a shame though as I'm > already using the program to program with (for all but user input and > debugging anyway...). Note that there are several stream variables: *standard-input* *standard-output* *trace-output* *error-output* *query-io* *terminal-io* *debug-io* All of them should be bound to some stream. But you can use SYNONYM-STREAM to redirect one to another. What you could in your IDE, is to provide some "terminal emulation" windows, hooked to these various stream. You could have only one, and use SYNONYM-STREAM to hook the threads to it. To implement the stream going between CL and this IDE window, you'd have to write a subclass of GRAY-STREAM (this is not in the CL standard, but a de-facto standard extension). These windows could be hidden, until the user writes to or reads from the associated stream. In some environment, even if the main user interface is on a GUI, the program can still use the terminal and the console for some of its stream I/O. (eg. on MacOSX you could use NSLog for the *trace-output* (at least in production code)). -- __Pascal Bourguignon__ http://www.informatimago.com/ IMPORTANT NOTICE TO PURCHASERS: The entire physical universe, including this product, may one day collapse back into an infinitesimally small space. Should another universe subsequently re-emerge, the existence of this product in that universe cannot be guaranteed. |
|
|||
|
On 2 Dec 2006 17:08:34 -0800, philip.armitage@gmail.com tried to confuse
everyone with this message: >Hi, > >I'm writing a newbie friendly IDE and have some basics up and running >but have hit my first problem: how to send user input back to Lisp. If >the user evaluates something like: > > (read-line) > >I'd like to activate an 'edit control' to type input (I'm using LTk but >I don't think any of this is library specific). You need to bind *standard-input* to a Gray stream which does what you want. The following example is in CLISP: (Warning: some parentheses may be unmatched) (defclass msgbox-in (gray:fundamental-character-input-stream) ((buffer :initform nil :accessor buffer))) (defmethod gray:stream-read-char :before ((s msgbox-in)) (unless (buffer s) (read-from-msgbox s))) ;;;read-from-msgbox shows input box and when the user enters something ;;;it fills (buffer s) with the contents of the text box. (defmethod gray:stream-read-char ((s msgbox-in)) (let* ((l (length (buffer s))) (c (when (> l 0) (elt (buffer s) 0))) (rest (when (> l 0) (subseq (buffer s) 1)))) (if c (progn (setf (buffer s) rest) c) (progn (setf (buffer s) nil) :eof)))) ;;This probably shouldn't be called when the buffer is empty ;;I don't even know when it is called at all (defmethod gray:stream-unread-char ((s msgbox-in) c) (let ((new (make-string (1+ (length (buffer s)))))) (setf (elt new 0) c) (setf (subseq new 1) (buffer s)) (setf (buffer s) new))) (defmethod gray:stream-read-line :before ((s msgbox-in)) (unless (buffer s) (read-from-msgbox s))) (defmethod gray:stream-read-line ((s msgbox-in)) (let ((what (buffer s))) (setf (buffer s) nil) what)) -- |Don't believe this - you're not worthless ,gr---------.ru |It's us against millions and we can't take them all... | ue il | |But we can take them on! | @ma | | (A Wilhelm Scream - The Rip) |______________| |
|
|||
|
On Dec 3, 1:08 am, philip.armit...@gmail.com wrote:
> but have hit my first problem: how to send user input back to Lisp. If Many thanks to everyone that replied. I tried a few of these ideas but I think I need to read up more about streams in Common Lisp. Thanks, Phil |
|
|
![]() |
| Thread Tools | |
| Display Modes | |
|
|
Similar Threads
|
||||
| Thread | Thread Starter | Forum | Replies | Last Post |
| Re: How to build Dynamic Variable names and values | Arthur Tabachneck | Newsgroup comp.soft-sys.sas | 0 | 02-11-2006 06:34 PM |
| Re: How to build Dynamic Variable names and values | SUBSCRIBE SAS-L Chandra Gadde | Newsgroup comp.soft-sys.sas | 0 | 02-11-2006 03:50 PM |
| Re: How to input data from different column for different rows | nospam@HOWLES.COM (Howard Schreier | Newsgroup comp.soft-sys.sas | 0 | 09-13-2005 03:47 PM |
| Re: surveyselect question | Zack, Matthew M. | Newsgroup comp.soft-sys.sas | 1 | 01-18-2005 06:26 PM |
| Re: surveyselect question | Scott | Newsgroup comp.soft-sys.sas | 0 | 01-16-2005 10:48 PM |