removed fancy jEdit console attributed stream

cvs
Slava Pestov 2005-07-17 20:29:17 +00:00
parent 34ba2a6bfc
commit 065b93dbdf
9 changed files with 135 additions and 419 deletions

View File

@ -151,11 +151,11 @@ public class ExternalFactor extends VocabularyLookup
/**
* Return a listener stream.
*/
public FactorStream openStream()
public Socket openStream()
{
try
{
return new FactorStream(openWireSocket());
return openWireSocket();
}
catch(Exception e)
{

View File

@ -1,145 +0,0 @@
/* :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;
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) throws IOException
{
this.socket = socket;
this.in = new DataInputStream(new BufferedInputStream(
socket.getInputStream()));
this.out = new DataOutputStream(new BufferedOutputStream(
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));
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;
//}}}
//{{{ 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 text)
throws Exception
{
this.text = text;
}
public String getText()
{
return text;
}
private String text;
} //}}}
}

View File

@ -33,6 +33,7 @@ import console.*;
import factor.*;
import javax.swing.text.AttributeSet;
import java.io.*;
import java.net.Socket;
import java.util.Iterator;
import java.util.HashMap;
import org.gjt.sp.jedit.jEdit;
@ -79,11 +80,11 @@ public class FactorShell extends Shell
public void printPrompt(Console console, Output output)
{
ConsoleState state = null;
try
{
state = getConsoleState(console);
state.openStream();
state.packetLoop(output);
}
catch(Exception e)
{
@ -111,7 +112,7 @@ public class FactorShell extends Shell
try
{
state = getConsoleState(console);
state.readResponse(command,output);
state.userInput(command);
}
catch(Exception e)
{
@ -181,13 +182,58 @@ public class FactorShell extends Shell
//}}}
//{{{ StreamThread class
static class StreamThread extends Thread
{
private Reader in;
private Output output;
StreamThread(Reader in, Output output)
{
this.in = in;
this.output = output;
}
public void run()
{
try
{
char[] buf = new char[4096];
for(;;)
{
int count = in.read(buf);
if(count <= 0)
break;
output.writeAttrs(null, new String(buf,0,count));
}
}
catch(IOException io)
{
Log.log(Log.ERROR,this,io);
}
finally
{
try
{
in.close();
}
catch(IOException io2)
{
Log.log(Log.ERROR,this,io2);
}
}
}
} //}}}
//{{{ ConsoleState class
class ConsoleState
{
private Console console;
private Output output;
private FactorStream stream;
private boolean waitingForInput;
private Reader in;
private Writer out;
private StreamThread thread;
ConsoleState(Console console)
{
@ -197,18 +243,19 @@ public class FactorShell extends Shell
void openStream()
{
if(stream != null)
if(thread != null)
return;
output.print(console.getInfoColor(),
jEdit.getProperty("factor.shell.opening"));
stream = null;
Socket socket = null;
ExternalFactor external = FactorPlugin.getExternalInstance();
if(external != null)
stream = external.openStream();
socket = external.openStream();
if(stream == null)
if(socket == null)
{
output.print(console.getInfoColor(),
jEdit.getProperty("factor.shell.no-connection"));
@ -217,98 +264,53 @@ public class FactorShell extends Shell
{
try
{
packetLoop(output);
in = new InputStreamReader(socket.getInputStream());
out = new OutputStreamWriter(socket.getOutputStream());
thread = new StreamThread(in,output);
thread.start();
}
catch(Exception e)
catch(IOException io)
{
Log.log(Log.ERROR,this,e);
Log.log(Log.ERROR,this,io);
in = null;
out = null;
thread = null;
try
{
socket.close();
}
catch(IOException io2)
{
Log.log(Log.ERROR,this,io2);
}
}
}
}
void closeStream()
{
try
if(thread != null)
{
if(stream != null)
{
waitingForInput = false;
output.print(console.getInfoColor(),
jEdit.getProperty("factor.shell.closing"));
stream.close();
}
}
catch(IOException e)
{
throw new RuntimeException(e);
output.print(console.getInfoColor(),
jEdit.getProperty("factor.shell.closing"));
thread.interrupt();
}
stream = null;
in = null;
out = null;
thread = null;
}
private void handleWritePacket(FactorStream.WritePacket w, Output output)
throws Exception
{
Cons pair = FactorPlugin.getExternalInstance()
.parseObject(w.getText());
String write;
if(pair.car instanceof String)
write = (String)pair.car;
else if(pair.car instanceof Integer)
write = String.valueOf((char)((Integer)pair.car).intValue());
else
write = "MALFORMED WRITE PACKET: " + pair;
AttributeSet attrs = new ListenerAttributeSet(
(Cons)pair.next().car);
output.writeAttrs(attrs,write);
}
void packetLoop(Output output) throws Exception
void userInput(String command) throws Exception
{
if(waitingForInput)
openStream();
if(thread == null)
return;
if(stream == null)
return;
for(;;)
{
FactorStream.Packet p = stream.nextPacket();
if(p == null)
{
/* EOF */
closeStream();
break;
}
else if(p instanceof FactorStream.ReadLinePacket)
{
waitingForInput = true;
break;
}
else if(p instanceof FactorStream.WritePacket)
handleWritePacket((FactorStream.WritePacket)p,output);
}
}
void readResponse(String command, Output output) throws Exception
{
if(waitingForInput)
{
openStream();
if(stream == null)
return;
stream.readResponse(command);
waitingForInput = false;
packetLoop(output);
}
else
{
output.print(console.getErrorColor(),
jEdit.getProperty("factor.shell.not-waiting"));
}
out.write(command);
out.write("\n");
out.flush();
}
} //}}}
}

View File

@ -1,103 +0,0 @@
/* :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 console.*;
import factor.Cons;
import javax.swing.text.*;
import javax.swing.*;
import java.awt.Color;
import org.gjt.sp.jedit.GUIUtilities;
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);
else if("actions".equals(key))
addAttribute(ConsolePane.Actions,createActionsMenu((Cons)value));
else if("icon".equals(key))
{
StyleConstants.setIcon(this,GUIUtilities.loadIcon(
"jeditresource:/Factor.jar!" + 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());
} //}}}
//{{{ createActionsMenu() method
private Action[] createActionsMenu(Cons alist)
{
int length = Cons.length(alist);
int i = 0;
Action[] actions = new Action[length];
while(alist != null)
{
Cons pair = (Cons)alist.car;
actions[i++] = new Console.EvalAction(
(String)pair.car,(String)pair.cdr);
alist = alist.next();
}
return actions;
} //}}}
}

View File

@ -45,7 +45,6 @@ compile? [
"Loading more library code..." print
t [
"/library/alien/malloc.factor"
"/library/io/buffer.factor"
@ -76,7 +75,6 @@ t [
"/library/io/logging.factor"
"/library/tools/telnetd.factor"
"/library/tools/jedit-wire.factor"
"/library/tools/jedit.factor"
"/library/httpd/load.factor"

View File

@ -78,10 +78,12 @@ M: complex unparse ( num -- str )
: unparse-ch ( ch -- ch/str )
dup quotable? [
dup ch>ascii-escape [ ] [ ch>unicode-escape ] ?ifte
] unless ;
,
] [
dup ch>ascii-escape [ ] [ ch>unicode-escape ] ?ifte %
] ifte ;
: unparse-string [ unparse-ch , ] each ;
: unparse-string [ unparse-ch ] each ;
M: string unparse ( str -- str )
[ CHAR: " , unparse-string CHAR: " , ] make-string ;

View File

@ -1,79 +0,0 @@
! Copyright (C) 2004, 2005 Slava Pestov.
! See http://factor.sf.net/license.txt for BSD license.
IN: jedit
USING: generic kernel listener lists namespaces parser
prettyprint sequences io strings words styles ;
! Wire protocol for jEdit to evaluate Factor code.
! Packets are of the form:
!
! 4 bytes length
! <n> bytes data
!
! jEdit sends a packet with code to eval, it receives the output
! captured with string-out.
: write-len ( seq -- ) length 4 >be write ;
: write-packet ( string -- ) dup write-len write flush ;
: read-packet ( -- string ) 4 read be> read ;
: wire-server ( -- )
#! Repeatedly read jEdit requests and execute them. Return
#! on EOF.
read-packet [ eval>string write-packet wire-server ] when* ;
! Stream protocol for jEdit allows user to interact with a
! Factor listener.
!
! Packets have the following form:
!
! 1 byte -- type. CHAR: w: write, CHAR: r: read CHAR: f flush
! 4 bytes -- for write only -- length of write request
! remaining -- unparsed write request -- string then style
! After a read line request, the server reads a response from
! the client:
! 4 bytes -- length. -1 means EOF
! remaining -- input
: jedit-write-attr ( str style -- )
CHAR: w write1
[ drop . f . ] string-out
dup write-len write ;
TUPLE: jedit-stream ;
M: jedit-stream stream-readln ( stream -- str )
[ CHAR: r write1 flush 4 read be> read ] with-wrapper ;
M: jedit-stream stream-write-attr ( str style stream -- )
[ jedit-write-attr ] with-wrapper ;
M: jedit-stream stream-flush ( stream -- )
[ CHAR: f write1 flush ] with-wrapper ;
C: jedit-stream ( stream -- stream )
[ >r <wrapper-stream> r> set-delegate ] keep ;
: stream-server ( -- )
#! Execute this in the inferior Factor.
stdio [ <jedit-stream> ] change print-banner ;
: jedit-lookup ( word -- list )
#! A utility word called by the Factor plugin to get some
#! required word info.
dup [
[
"vocabulary"
"name"
"stack-effect"
] [
dupd word-prop
] map >r definer r> cons
] when ;
: completions ( str pred -- list | pred: str word -- ? )
#! Make a list of completions. Each element of the list is
#! a vocabulary/name/stack-effect triplet list.
word-subset-with [ jedit-lookup ] map ;

View File

@ -4,6 +4,9 @@ IN: jedit
USING: kernel lists namespaces parser sequences io strings
unparser words ;
! Some words to send requests to a running jEdit instance to
! edit files and position the cursor on a specific line number.
: jedit-server-file ( -- path )
"jedit-server-file" get
[ "~" get "/.jedit/server" append ] unless* ;
@ -44,3 +47,41 @@ unparser words ;
] [
2drop "Unknown source" print
] ifte ;
! Wire protocol for jEdit to evaluate Factor code.
! Packets are of the form:
!
! 4 bytes length
! <n> bytes data
!
! jEdit sends a packet with code to eval, it receives the output
! captured with string-out.
: write-len ( seq -- ) length 4 >be write ;
: write-packet ( string -- ) dup write-len write flush ;
: read-packet ( -- string ) 4 read be> read ;
: wire-server ( -- )
#! Repeatedly read jEdit requests and execute them. Return
#! on EOF.
read-packet [ eval>string write-packet wire-server ] when* ;
: jedit-lookup ( word -- list )
#! A utility word called by the Factor plugin to get some
#! required word info.
dup [
[
"vocabulary"
"name"
"stack-effect"
] [
dupd word-prop
] map >r definer r> cons
] when ;
: completions ( str pred -- list | pred: str word -- ? )
#! Make a list of completions. Each element of the list is
#! a vocabulary/name/stack-effect triplet list.
word-subset-with [ jedit-lookup ] map ;

View File

@ -4,7 +4,7 @@ IN: telnetd
USING: errors listener kernel namespaces io threads parser ;
: telnet-client ( socket -- )
dup [ log-client listener ] with-stream ;
dup [ log-client print-banner listener ] with-stream ;
: telnet-connection ( socket -- )
[ telnet-client ] in-thread drop ;