]> gitweb.factorcode.org Git - factor.git/commitdiff
overhauling plugin
authorSlava Pestov <slava@factorcode.org>
Sat, 13 Nov 2004 23:07:18 +0000 (23:07 +0000)
committerSlava Pestov <slava@factorcode.org>
Sat, 13 Nov 2004 23:07:18 +0000 (23:07 +0000)
20 files changed:
TODO.FACTOR.txt
actions.xml
examples/mandel.factor
factor/FactorReader.java
factor/jedit/ExternalFactor.java [new file with mode: 0644]
factor/jedit/FactorPlugin.java
factor/jedit/FactorPlugin.props
factor/jedit/FactorShell.java
factor/jedit/FactorStream.java [new file with mode: 0644]
factor/jedit/ListenerAttributeSet.java [new file with mode: 0644]
library/eval-catch.factor [new file with mode: 0644]
library/platform/jvm/parser.factor
library/platform/native/boot-stage2.factor
library/platform/native/in-thread.factor
library/test/io/io.factor
library/test/parser.factor
library/tools/listener.factor
native/string.c
native/string.h
native/write.c

index d0e0f59f75f2f44e1d5567a95aa3838617b7485a..bd4de39fb908b9d15431d936a8aa51127c08b9e9 100644 (file)
@@ -30,7 +30,6 @@
 \r
 + listener/plugin:\r
 \r
-- extract word in wrong place\r
 - accept multi-line input in listener\r
 - don't show listener on certain commands\r
 - NPE in ErrorHighlight\r
index 81e24360639a1ed8c5a98677a32cef1dec4b009d..b120aabaf6d14b34c3c6a20c86c243a3599a6b0f 100644 (file)
@@ -3,6 +3,12 @@
 <!DOCTYPE ACTIONS SYSTEM "actions.dtd">
 
 <ACTIONS>
+       <ACTION NAME="factor-restart">
+               <CODE>
+                       FactorPlugin.stopExternalInstance();
+                       FactorPlugin.getExternalInstance();
+               </CODE>
+       </ACTION>
        <ACTION NAME="factor-eval-selection">
                <CODE>
                        sel = textArea.selectedText;
index 3f19b7aa866a7881f4df7ab65cbb9f9b32cc65ed..61466d51827aaca6dce264855301064ba13939ef 100644 (file)
@@ -1,7 +1,7 @@
 ! Graphical mandelbrot fractal renderer.
 ! To run this code, start your interpreter like so:
 !
-! ./f -library:sdl=libSDL.so -library:sdl-gfx=libSDL_gfx.so
+! ./f -libraries:sdl=libSDL.so -libraries:sdl-gfx=libSDL_gfx.so
 !
 ! Then, enter this at the interpreter prompt:
 !
index b82b46791a6afa76951bcedfc297bc1407395ad9..d30d82bf828a777f1c73b7391e7faafa12786faf 100644 (file)
@@ -482,8 +482,7 @@ public class FactorReader
                ParseState state = getCurrentState();
                if(state.start != start)
                        scanner.error(end + " does not close " + state.start);
-               else
-                       states = states.next();
+               states = states.next();
                return state;
        } //}}}
 
diff --git a/factor/jedit/ExternalFactor.java b/factor/jedit/ExternalFactor.java
new file mode 100644 (file)
index 0000000..c8b1de4
--- /dev/null
@@ -0,0 +1,143 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.FactorInterpreter;
+import java.io.*;
+import java.net.Socket;
+import java.util.*;
+import org.gjt.sp.util.Log;
+
+/**
+ * Encapsulates a connection to an external Factor instance.
+ */
+public class ExternalFactor
+{
+       //{{{ ExternalFactor constructor
+       /**
+        * We are given two streams that point to a bare REPL.
+        */
+       public ExternalFactor(FactorInterpreter interp, InputStream in, OutputStream out)
+               throws IOException
+       {
+               this.interp = interp;
+               this.in = new DataInputStream(in);
+               this.out = new DataOutputStream(out);
+
+               out.write("USE: jedit wire-server\n".getBytes("ASCII"));
+               out.flush();
+
+               waitForAck();
+
+               /* Start stream server */
+               streamServer = 9999;
+               eval("USE: telnetd [ 9999 telnetd ] in-thread");
+       } //}}}
+
+       //{{{ waitForAck() method
+       private void waitForAck() throws IOException
+       {
+               sendEval("\"ACK\" write flush\n");
+
+               /* Read everything until wire header */
+               String discardStr = "";
+
+               while(!discardStr.endsWith("ACK"))
+               {
+                       byte[] discard = new byte[2048];
+                       int len = in.read(discard,0,discard.length);
+                       discardStr = new String(discard,0,len);
+               }
+       } //}}}
+       
+       //{{{ sendEval() method
+       private void sendEval(String cmd) throws IOException
+       {
+               byte[] bytes = cmd.getBytes("ASCII");
+               out.writeInt(bytes.length);
+               out.write(bytes,0,bytes.length);
+               out.flush();
+       } //}}}
+
+       //{{{ eval() method
+       /**
+        * Send a command to the inferior Factor, and return the string output.
+        */
+       public synchronized String eval(String cmd) throws IOException
+       {
+               waitForAck();
+
+               sendEval(cmd);
+
+               int responseLength = in.readInt();
+               byte[] response = new byte[responseLength];
+               in.readFully(response);
+               
+               return new String(response,"ASCII");
+       } //}}}
+
+       //{{{ openStream() method
+       /**
+        * Return a listener stream.
+        */
+       public FactorStream openStream() throws IOException
+       {
+               Socket client = new Socket("localhost",streamServer);
+               return new FactorStream(client,interp);
+       } //}}}
+
+       //{{{ close() method
+       /**
+        * Close communication session. Factor will then exit.
+        */
+       public synchronized void close()
+       {
+               try
+               {
+                       /* don't care about response */
+                       sendEval("0 exit*");
+                       in.close();
+                       out.close();
+               }
+               catch(Exception e)
+               {
+                       // We don't care...
+                       Log.log(Log.DEBUG,this,e);
+               }
+       } //}}}
+
+       //{{{ Private members
+       private FactorInterpreter interp;
+       private DataInputStream in;
+       private DataOutputStream out;
+       
+       private int streamServer;
+       //}}}
+}
index a53546b1ccefabc55b614bb23db2e5fe92d9a812..8ed881631355d4b64f9b8adbe5ba8c4a34bd1836 100644 (file)
@@ -30,7 +30,7 @@
 package factor.jedit;
 
 import factor.*;
-import java.io.InputStreamReader;
+import java.io.*;
 import java.util.*;
 import org.gjt.sp.jedit.gui.*;
 import org.gjt.sp.jedit.textarea.*;
@@ -41,14 +41,84 @@ import sidekick.*;
 public class FactorPlugin extends EditPlugin
 {
        private static FactorInterpreter interp;
+       private static ExternalFactor external;
 
+       //{{{ getPluginPath() method
+       private String getPluginPath()
+       {
+               return MiscUtilities.getParentOfPath(
+                       jEdit.getPlugin("factor.jedit.FactorPlugin")
+                       .getPluginJAR().getPath())
+                       + "Factor";
+       } //}}}
+       
        //{{{ start() method
        public void start()
        {
                BeanShell.eval(null,BeanShell.getNameSpace(),
                        "import factor.*;\nimport factor.jedit.*;\n");
+               String program = jEdit.getProperty("factor.external.program");
+               String image = jEdit.getProperty("factor.external.image");
+               if(program == null || image == null
+                       || program.length() == 0 || image.length() == 0)
+               {
+                       jEdit.setProperty("factor.external.program",
+                               MiscUtilities.constructPath(getPluginPath(),"f"));
+                       jEdit.setProperty("factor.external.image",
+                               MiscUtilities.constructPath(getPluginPath(),"factor.image"));
+               }
+       } //}}}
+
+       //{{{ stop() method
+       public void stop()
+       {
+               stopExternalInstance();
        } //}}}
        
+       //{{{ getExternalInstance() method
+       /**
+        * Returns the object representing a connection to an external Factor instance.
+        * It will start the interpreter if it's not already running.
+        */
+       public static ExternalFactor getExternalInstance()
+               throws IOException, UnsupportedEncodingException
+       {
+               if(external == null)
+               {
+                       Process p = Runtime.getRuntime().exec(
+                               new String[] {
+                                       jEdit.getProperty("factor.external.program"),
+                                       jEdit.getProperty("factor.external.image"),
+                                       "-no-ansi",
+                                       "-jedit"
+                               });
+                       p.getErrorStream().close();
+
+                       external = new ExternalFactor(
+                               getInterpreter(),
+                               p.getInputStream(),
+                               p.getOutputStream());
+               }
+
+               return external;
+       } //}}}
+
+       //{{{ stopExternalInstance() method
+       /**
+        * Stops the external interpreter. It will probably be restarted soon after.
+        */
+       public static void stopExternalInstance()
+       {
+               ((FactorShell)ServiceManager.getService("console.Shell","Factor"))
+                       .closeStreams();
+
+               if(external != null)
+               {
+                       external.close();
+                       external = null;
+               }
+       } //}}}
+
        //{{{ newInterpreter() method
        private static FactorInterpreter newInterpreter(String[] args)
        {
@@ -75,7 +145,7 @@ public class FactorPlugin extends EditPlugin
        {
                if(interp == null)
                {
-                       interp = newInterpreter(new String[] { "-jedit" });
+                       interp = newInterpreter(new String[] { "-jedit", "-no-compile" });
                }
 
                return interp;
index 1a276f1cdc9cb3fb803f7d6dcd338d1bc3591e66..edd0dcee5a07d157c8d570d138d3b0b4c5e6dc31 100644 (file)
@@ -1,5 +1,4 @@
 ### Plugin properties
-
 plugin.factor.jedit.FactorPlugin.activate=startup
 
 plugin.factor.jedit.FactorPlugin.name=Factor
@@ -12,6 +11,7 @@ plugin.factor.jedit.FactorPlugin.depend.1=plugin errorlist.ErrorListPlugin 1.3.2
 plugin.factor.jedit.FactorPlugin.depend.2=plugin sidekick.SideKickPlugin 0.3.1
 plugin.factor.jedit.FactorPlugin.depend.3=plugin console.ConsolePlugin 4.0.1
 
+#! Menu
 plugin.factor.jedit.FactorPlugin.menu=factor-run-file \
        factor-eval-selection \
        - \
@@ -23,7 +23,9 @@ plugin.factor.jedit.FactorPlugin.menu=factor-run-file \
        factor-see \
        factor-usages \
        - \
-       factor-extract-word
+       factor-extract-word \
+       - \
+       factor-restart
 
 factor-run-file.label=Run current file
 factor-eval-selection.label=Evaluate selection
@@ -34,7 +36,9 @@ factor-edit.label=Edit word at caret
 factor-edit-dialog.label=Edit word...
 factor-usages.label=Word usages at caret
 factor-extract-word.label=Extract word...
+factor-restart.label=Restart Factor
 
+# SideKick stuff
 sidekick.parser.factor.label=Factor
 mode.factor.sidekick.parser=factor
 
@@ -46,6 +50,7 @@ factor.completion.stack=: <b>{0}</b> {1}
 factor.completion.shuffle=~&lt;&lt; <b>{0}</b> {1} &gt;&gt;~
 factor.completion.symbol=SYMBOL: <b>{0}</b>
 
+# Dialog boxes
 factor.status.inserted-use=Inserted {0}
 factor.status.already-used=Already used {0}
 
@@ -60,3 +65,17 @@ factor.extract-word.message=Enter name of new word:
 
 factor.extract-word-where.title=Cannot Extract Here
 factor.extract-word-where.message=This command can only be used inside a word definition.
+
+# Shell
+factor.shell.opening=Opening listener connection
+factor.shell.closing=Closing listener connection
+factor.shell.not-waiting=Not accepting input at this time
+
+# Option pane
+plugin.factor.jedit.FactorPlugin.option-pane=factor
+
+options.factor.label=Factor
+options.factor.code=new factor.jedit.FactorOptionPane();
+options.factor.program=Factor runtime executable:
+options.factor.image=Factor image:
+options.factor.choose=Choose file...
index 32c506455448667764a12157ccf46f0cde17e951..1968ba18f06d030aa95d5e8071186381a14c9e28 100644 (file)
@@ -32,28 +32,19 @@ package factor.jedit;
 import console.*;
 import factor.*;
 import javax.swing.text.AttributeSet;
+import java.io.IOException;
+import java.util.Iterator;
 import java.util.WeakHashMap;
+import org.gjt.sp.jedit.jEdit;
 import org.gjt.sp.jedit.ServiceManager;
+import org.gjt.sp.util.Log;
 
 public class FactorShell extends Shell
 {
-       //{{{ readLine() method
-       /**
-        * Helper static method to simplify Factor code.
-        */
-       public static void readLine(Cons continuation, Console console)
-       {
-               FactorShell shell = (FactorShell)ServiceManager.getService(
-                       "console.Shell","Factor");
-               ConsoleState state = shell.getConsoleState(console);
-               state.readLineContinuation = continuation;
-       } //}}}
-       
        //{{{ FactorShell constructor
        public FactorShell()
        {
                super("Factor");
-               interp = FactorPlugin.getInterpreter();
                consoles = new WeakHashMap();
        } //}}}
 
@@ -75,7 +66,15 @@ public class FactorShell extends Shell
         */
        public void printPrompt(Console console, Output output)
        {
-               getConsoleState(console);
+               try
+               {
+                       getConsoleState(console).packetLoop(output);
+               }
+               catch(Exception e)
+               {
+                       output.print(console.getErrorColor(),e.toString());
+                       Log.log(Log.ERROR,this,e);
+               }
        } //}}}
 
        //{{{ execute() method
@@ -91,11 +90,20 @@ public class FactorShell extends Shell
        public void execute(Console console, String input,
                Output output, Output error, String command)
        {
-               ConsoleState state = getConsoleState(console);
-               Cons quot = new Cons(command,state.readLineContinuation);
-               eval(quot);
-               output.commandDone();
-               error.commandDone();
+               try
+               {
+                       getConsoleState(console).readResponse(output,command);
+               }
+               catch(Exception e)
+               {
+                       output.print(console.getErrorColor(),e.toString());
+                       Log.log(Log.ERROR,this,e);
+               }
+               finally
+               {
+                       output.commandDone();
+                       error.commandDone();
+               }
        } //}}}
        
        //{{{ stop() method
@@ -105,54 +113,120 @@ public class FactorShell extends Shell
        public void stop(Console console)
        {
        } //}}}
-       
+
+       //{{{ closeStreams() method
+       /**
+        * Close all listener connections. Should be called before Factor is restarted.
+        */
+       public void closeStreams()
+       {
+               Iterator iter = consoles.values().iterator();
+               while(iter.hasNext())
+               {
+                       ConsoleState state = (ConsoleState)iter.next();
+                       state.closeStream();
+               }
+       } //}}}
+
        //{{{ Private members
-       private FactorInterpreter interp;
        private WeakHashMap consoles;
        
        //{{{ getConsoleState() method
        private ConsoleState getConsoleState(Console console)
+               throws IOException
        {
                ConsoleState state = (ConsoleState)consoles.get(console);
                if(state == null)
                {
                        state = new ConsoleState(console);
                        consoles.put(console,state);
-
-                       eval(new Cons(console,
-                               new Cons(interp.searchVocabulary(
-                                       "console","console-hook"),
-                                       null)));
                }
                return state;
        } //}}}
 
-       //{{{ eval() method
-       private void eval(Cons cmd)
-       {
-               try
-               {
-                       interp.call(cmd);
-                       interp.run();
-               }
-               catch(Exception e)
-               {
-                       System.err.println("Failed to eval " + cmd + ":");
-                       e.printStackTrace();
-               }
-       } //}}}
-
        //}}}
 
        //{{{ ConsoleState class
        class ConsoleState
        {
                private Console console;
-               Cons readLineContinuation;
+               private FactorStream stream;
+               private boolean waitingForInput;
                
                ConsoleState(Console console)
                {
                        this.console = console;
                }
+
+               void openStream(Output output) throws Exception
+               {
+                       if(stream == null)
+                       {
+                               output.print(console.getInfoColor(),
+                                       jEdit.getProperty("factor.shell.opening"));
+                               stream = FactorPlugin.getExternalInstance().openStream();
+                       }
+               }
+
+               void closeStream()
+               {
+                       try
+                       {
+                               if(stream != null)
+                               {
+                                       waitingForInput = false;
+                                       console.print(console.getInfoColor(),
+                                               jEdit.getProperty("factor.shell.closing"));
+                                       stream.close();
+                                       stream = null;
+                               }
+                       }
+                       catch(IOException e)
+                       {
+                               /* We don't care */
+                               Log.log(Log.ERROR,this,e);
+                       }
+               }
+               
+               void packetLoop(Output output) throws Exception
+               {
+                       if(waitingForInput)
+                               return;
+
+                       openStream(output);
+
+                       FactorStream.Packet p;
+                       while((p = stream.nextPacket()) != null)
+                       {
+                               if(p instanceof FactorStream.ReadLinePacket)
+                               {
+                                       waitingForInput = true;
+                                       break;
+                               }
+                               else if(p instanceof FactorStream.WritePacket)
+                               {
+                                       FactorStream.WritePacket w
+                                               = (FactorStream.WritePacket)p;
+                                       output.writeAttrs(w.getAttributes(),w.getText());
+                               }
+                       }
+               }
+
+               void readResponse(Output output, String command) throws Exception
+               {
+                       if(waitingForInput)
+                       {
+                               openStream(output);
+
+                               stream.readResponse(command);
+                               waitingForInput = false;
+                               packetLoop(output);
+                       }
+                       else
+                       {
+                               console.print(console.getErrorColor(),
+                                       jEdit.getProperty("factor.shell.not-waiting"));
+                       }
+               }
        } //}}}
 }
diff --git a/factor/jedit/FactorStream.java b/factor/jedit/FactorStream.java
new file mode 100644 (file)
index 0000000..a9881bb
--- /dev/null
@@ -0,0 +1,161 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import factor.Cons;
+import factor.FactorInterpreter;
+import factor.FactorReader;
+import javax.swing.text.AttributeSet;
+import java.io.*;
+import java.net.Socket;
+import java.util.*;
+
+/**
+ * Encapsulates a Factor listener connection.
+ */
+public class FactorStream
+{
+       //{{{ FactorStream constructor
+       /**
+        * We are given a socket that points to a bare REPL.
+        */
+       public FactorStream(Socket socket, FactorInterpreter interp) throws IOException
+       {
+               this.interp = interp;
+               this.socket = socket;
+               this.in = new DataInputStream(socket.getInputStream());
+               this.out = new DataOutputStream(socket.getOutputStream());
+
+               out.write("\"\\0\" write flush USE: jedit stream-server\n".getBytes("ASCII"));
+               out.flush();
+
+               /* Read everything until prompt */
+               int b = -2;
+               while(b != '\0' && b != -1)
+                       b = in.read();
+       } //}}}
+
+       //{{{ nextPacket() method
+       /**
+        * @return null on EOF.
+        */
+       public Packet nextPacket() throws Exception
+       {
+               int ch = in.read();
+               switch(ch)
+               {
+               case 'r':
+                       return new ReadLinePacket();
+               case 'f':
+                       return new FlushPacket();
+               case 'w':
+                       int len = in.readInt();
+                       byte[] request = new byte[len];
+                       in.readFully(request);
+                       return new WritePacket(new String(request,0,len),interp);
+               case -1:
+                       return null;
+               default:
+                       throw new IOException("Bad stream packet type: " + ch);
+               }
+       } //}}}
+       
+       //{{{ readResponse() method
+       /**
+        * This must only be called if the last packet received was a read request.
+        */
+       public void readResponse(String input) throws IOException
+       {
+               int len = input.length();
+               out.writeInt(len);
+               out.write(input.getBytes("ASCII"),0,len);
+               out.flush();
+       } //}}}
+
+       //{{{ close() method
+       /**
+        * Close communication session. Factor will then exit.
+        */
+       public void close() throws IOException
+       {
+               socket.close();
+               in.close();
+               out.close();
+       } //}}}
+
+       //{{{ Private members
+       private Socket socket;
+       private DataInputStream in;
+       private DataOutputStream out;
+       private FactorInterpreter interp;
+       //}}}
+       
+       //{{{ Packet class
+       public static abstract class Packet {}
+       //}}}
+       
+       //{{{ ReadLinePacket class
+       public static class ReadLinePacket extends Packet {}
+       //}}}
+       
+       //{{{ FlushPacket class
+       public static class FlushPacket extends Packet {}
+       //}}}
+       
+       //{{{ WritePacket class
+       public static class WritePacket extends Packet
+       {
+               public WritePacket(String input, FactorInterpreter interp)
+                       throws Exception
+               {
+                       FactorReader parser = new FactorReader(
+                               "parseObject()",
+                               new BufferedReader(new StringReader(input)),
+                               true,false,interp);
+                       Cons pair = parser.parse();
+
+                       this.write = (String)pair.car;
+                       this.attrs = new ListenerAttributeSet((Cons)pair.next().car);
+               }
+               
+               public String getText()
+               {
+                       return write;
+               }
+
+               public AttributeSet getAttributes()
+               {
+                       return attrs;
+               }
+
+               private String write;
+               private AttributeSet attrs;
+       } //}}}
+}
diff --git a/factor/jedit/ListenerAttributeSet.java b/factor/jedit/ListenerAttributeSet.java
new file mode 100644 (file)
index 0000000..56f2ba4
--- /dev/null
@@ -0,0 +1,76 @@
+/* :folding=explicit:collapseFolds=1: */
+
+/*
+ * $Id$
+ *
+ * Copyright (C) 2004 Slava Pestov.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright notice,
+ *    this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright notice,
+ *    this list of conditions and the following disclaimer in the documentation
+ *    and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+ * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+ * FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+ * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+ * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+ * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+package factor.jedit;
+
+import javax.swing.text.*;
+import java.awt.Color;
+import factor.Cons;
+
+public class ListenerAttributeSet extends SimpleAttributeSet
+{
+       //{{{ ListenerAttributeSet constructor
+       ListenerAttributeSet(Cons alist)
+       {
+               while(alist != null)
+               {
+                       Cons pair = (Cons)alist.car;
+                       handleAttribute(pair.car,pair.cdr);
+                       alist = alist.next();
+               }
+       } //}}}
+       
+       //{{{ handleAttribute() method
+       private void handleAttribute(Object key, Object value)
+       {
+               if("bold".equals(key))
+                       addAttribute(StyleConstants.Bold,Boolean.TRUE);
+               else if("italics".equals(key))
+                       addAttribute(StyleConstants.Italic,Boolean.TRUE);
+               else if("underline".equals(key))
+                       addAttribute(StyleConstants.Underline,Boolean.TRUE);
+               else if("fg".equals(key))
+                       addAttribute(StyleConstants.Foreground,toColor((Cons)value));
+               else if("bg".equals(key))
+                       addAttribute(StyleConstants.Background,toColor((Cons)value));
+               else if("font".equals(key))
+                       addAttribute(StyleConstants.FontFamily,value);
+               else if("size".equals(key))
+                       addAttribute(StyleConstants.FontSize,value);
+       } //}}}
+       
+       //{{{ toColor() method
+       private Color toColor(Cons color)
+       {
+               Number r = (Number)color.car;
+               Number g = (Number)color.next().car;
+               Number b = (Number)color.next().next().car;
+               return new Color(r.intValue(),g.intValue(),b.intValue());
+       } //}}}
+}
diff --git a/library/eval-catch.factor b/library/eval-catch.factor
new file mode 100644 (file)
index 0000000..216f3bc
--- /dev/null
@@ -0,0 +1,38 @@
+! :folding=indent:collapseFolds=1:
+
+! $Id$
+!
+! Copyright (C) 2004 Slava Pestov.
+! 
+! Redistribution and use in source and binary forms, with or without
+! modification, are permitted provided that the following conditions are met:
+! 
+! 1. Redistributions of source code must retain the above copyright notice,
+!    this list of conditions and the following disclaimer.
+! 
+! 2. Redistributions in binary form must reproduce the above copyright notice,
+!    this list of conditions and the following disclaimer in the documentation
+!    and/or other materials provided with the distribution.
+! 
+! THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
+! INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
+! FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+! DEVELOPERS AND CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+! SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+! PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
+! OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+! WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
+! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
+! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+
+IN: parser
+USE: errors
+USE: stack
+USE: combinators
+USE: stdio
+
+: eval-catch ( str -- )
+    [ eval ] [ [ default-error-handler drop ] when* ] catch ;
+
+: eval>string ( in -- out )
+    [ eval-catch ] with-string ;
index dbc12b9f062ef81ca15be8d76912c86fffabe626..415a6b8f9b169f21ef89d940ce42bcfd50b896e6 100644 (file)
@@ -81,6 +81,9 @@ USE: strings
 : eval ( "X" -- X )
     parse call ;
 
+: eval-catch ( str -- )
+    [ eval ] [ [ default-error-handler drop ] when* ] catch ;
+
 : parse-number* ( str base -- num )
     #! Convert a string to a number. Return f if conversion
     #! fails.
index b92248101ec3c6756579faa271d13eb22ae2b936..2d9437932354e5f617ecd850378cdd923fe65bc5 100644 (file)
@@ -102,6 +102,7 @@ USE: stdio
     "/library/platform/native/prettyprint.factor"
     "/library/platform/native/files.factor"
     "/library/files.factor"
+    "/library/eval-catch.factor"
     "/library/tools/listener.factor"
     "/library/tools/inspector.factor"
     "/library/tools/word-tools.factor"
@@ -109,6 +110,7 @@ USE: stdio
     "/library/ansi.factor"
     "/library/tools/telnetd.factor"
     "/library/tools/inferior.factor"
+    "/library/tools/jedit-wire.factor"
     "/library/platform/native/profiler.factor"
     "/library/platform/native/heap-stats.factor"
     "/library/platform/native/gensym.factor"
index b6f23fb729167f18078cc67932eb7e6f0e83e226..dfdf977673133d15b9d382d402fa34c7dfa5ce38 100644 (file)
@@ -42,6 +42,9 @@ USE: stack
     #! I/O or an explicit call to 'yield'.
     [
         schedule-thread
+        ! Clear stacks since we never go up from this point
+        { } set-catchstack
+        { } set-callstack
         [
             call
         ] [
index 247450d65ed0f619ed94806a2ff9dbb230eb3231..bc28b01b421f16159cb2d9b52a67172672f5a0c4 100644 (file)
@@ -39,3 +39,6 @@ USE: math
     "/library/test/io/binary.txt" <resource-stream>
     [ read1 ] with-stream >fixnum
 ] unit-test
+
+! Make sure we use correct to_c_string form when writing
+[ ] [ "\0" write ] unit-test
index c0f253d8022fc0709e3b229f0701fd1df13bf535..63ea6795b071b9195673ed8ab7bdae272a461ee0 100644 (file)
@@ -60,3 +60,7 @@ test-word
 
 ! Test EOL comments in multiline strings.
 [ [ "Hello" ] ] [ "#! This calls until-eol.\n\"Hello\"" parse ] unit-test 
+
+[ 4 ] [ "2 2 +" eval-catch ] unit-test
+[ "4\n" ] [ "2 2 + ." eval>string ] unit-test
+[ ] [ "fdafdf" eval-catch ] unit-test
index 93b7feb92068c955443154c13b9d4627e3717c98..b62137c32cc576340649555a9c73829af0588d45 100644 (file)
@@ -64,9 +64,6 @@ USE: vectors
 : exit ( -- )
     "quit-flag" on ;
 
-: eval-catch ( str -- )
-    [ eval ] [ [ default-error-handler drop ] when* ] catch ;
-
 : listener-step ( -- )
     print-prompt read [ eval-catch ] [ exit ] ifte* ;
 
index 66cbae3d6e433e877e9ea3b9479c73a4380f95b6..85022d0664156f4235649553e3243f81d0c80c1c 100644 (file)
@@ -86,19 +86,29 @@ void box_c_string(const BYTE* c_string)
 /* untagged */
 BYTE* to_c_string(STRING* s)
 {
-       STRING* _c_str = allot_string(s->capacity / CHARS + 1);
        CELL i;
 
-       BYTE* c_str = (BYTE*)(_c_str + 1);
-       
        for(i = 0; i < s->capacity; i++)
        {
                CHAR ch = string_nth(s,i);
                if(ch == '\0' || ch > 255)
                        general_error(ERROR_C_STRING,tag_object(s));
-               c_str[i] = string_nth(s,i);
        }
 
+       return to_c_string_unchecked(s);
+}
+
+/* untagged */
+BYTE* to_c_string_unchecked(STRING* s)
+{
+       STRING* _c_str = allot_string(s->capacity / CHARS + 1);
+       CELL i;
+
+       BYTE* c_str = (BYTE*)(_c_str + 1);
+       
+       for(i = 0; i < s->capacity; i++)
+               c_str[i] = string_nth(s,i);
+
        c_str[s->capacity] = '\0';
 
        return c_str;
index 146655aab433a62e82fb7ea8eaf6f64901cbff5a..b96a9ed3427fbc5be3f23959e3ec3d6e4734ee3a 100644 (file)
@@ -18,6 +18,7 @@ FIXNUM hash_string(STRING* str, FIXNUM len);
 void rehash_string(STRING* str);
 STRING* grow_string(STRING* string, FIXNUM capacity, CHAR fill);
 BYTE* to_c_string(STRING* s);
+BYTE* to_c_string_unchecked(STRING* s);
 void box_c_string(const BYTE* c_string);
 STRING* from_c_string(const BYTE* c_string);
 BYTE* unbox_c_string(void);
index c64a5ab541d4299ad0f1c4f6808a5ea3e20cf161..64741f275f8f0774f8cbd7e7c332fc35100021bc 100644 (file)
@@ -110,7 +110,7 @@ void write_string_8(PORT* port, STRING* str)
        if(!can_write(port,str->capacity))
                io_error(__FUNCTION__);
 
-       c_str = to_c_string(str);
+       c_str = to_c_string_unchecked(str);
        write_string_raw(port,c_str,str->capacity);
 }