more work on jedit plugin
parent
0b73b1c864
commit
26cc9ba32c
|
@ -3,6 +3,7 @@
|
||||||
|
|
||||||
+ listener:
|
+ listener:
|
||||||
|
|
||||||
|
- top level broken
|
||||||
- link style lingers
|
- link style lingers
|
||||||
- back space then type: input style gone
|
- back space then type: input style gone
|
||||||
- fedit broken with listener
|
- fedit broken with listener
|
||||||
|
|
|
@ -87,6 +87,18 @@ public class FactorScanner
|
||||||
this.readtable = readtable;
|
this.readtable = readtable;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ getLineNumber() method
|
||||||
|
public int getLineNumber()
|
||||||
|
{
|
||||||
|
return lineNo;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ getFileName() method
|
||||||
|
public String getFileName()
|
||||||
|
{
|
||||||
|
return filename;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ nextLine() method
|
//{{{ nextLine() method
|
||||||
private void nextLine() throws IOException
|
private void nextLine() throws IOException
|
||||||
{
|
{
|
||||||
|
|
|
@ -73,6 +73,12 @@ public class FactorWord implements FactorExternalizable, FactorObject
|
||||||
public FactorClassLoader loader;
|
public FactorClassLoader loader;
|
||||||
public String className;
|
public String className;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For text editor integration.
|
||||||
|
*/
|
||||||
|
public String file;
|
||||||
|
public int line;
|
||||||
|
|
||||||
private FactorNamespace namespace;
|
private FactorNamespace namespace;
|
||||||
|
|
||||||
//{{{ FactorWord constructor
|
//{{{ FactorWord constructor
|
||||||
|
|
|
@ -31,13 +31,23 @@ package factor.jedit;
|
||||||
|
|
||||||
import factor.listener.FactorListenerPanel;
|
import factor.listener.FactorListenerPanel;
|
||||||
import factor.FactorInterpreter;
|
import factor.FactorInterpreter;
|
||||||
|
import org.gjt.sp.jedit.gui.*;
|
||||||
import org.gjt.sp.jedit.*;
|
import org.gjt.sp.jedit.*;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
|
||||||
public class FactorPlugin extends EditPlugin
|
public class FactorPlugin extends EditPlugin
|
||||||
{
|
{
|
||||||
|
private static final String DOCKABLE_NAME = "factor";
|
||||||
|
|
||||||
private static WeakHashMap views = new WeakHashMap();
|
private static WeakHashMap views = new WeakHashMap();
|
||||||
|
|
||||||
|
//{{{ start() method
|
||||||
|
public void start()
|
||||||
|
{
|
||||||
|
/* Macros.registerHandler(new FactorMacroHandler()); */
|
||||||
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ getInterpreter() method
|
||||||
public static FactorInterpreter getInterpreter(View view)
|
public static FactorInterpreter getInterpreter(View view)
|
||||||
{
|
{
|
||||||
FactorInterpreter interp = (FactorInterpreter)
|
FactorInterpreter interp = (FactorInterpreter)
|
||||||
|
@ -49,5 +59,15 @@ public class FactorPlugin extends EditPlugin
|
||||||
views.put(view,interp);
|
views.put(view,interp);
|
||||||
}
|
}
|
||||||
return interp;
|
return interp;
|
||||||
}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ eval() method
|
||||||
|
public static void eval(View view, String cmd)
|
||||||
|
{
|
||||||
|
DockableWindowManager wm = view.getDockableWindowManager();
|
||||||
|
wm.addDockableWindow(DOCKABLE_NAME);
|
||||||
|
FactorListenerPanel panel = (FactorListenerPanel)
|
||||||
|
wm.getDockableWindow(DOCKABLE_NAME);
|
||||||
|
panel.getListener().eval(cmd);
|
||||||
|
} //}}}
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,8 +119,27 @@ public class FactorListener extends JTextPane
|
||||||
listenerList.remove(EvalListener.class,l);
|
listenerList.remove(EvalListener.class,l);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ eval() method
|
||||||
|
public void eval(String eval)
|
||||||
|
{
|
||||||
|
if(eval == null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
StyledDocument doc = (StyledDocument)getDocument();
|
||||||
|
doc.insertString(doc.getLength(),eval + "\n",
|
||||||
|
getCharacterAttributes());
|
||||||
|
}
|
||||||
|
catch(BadLocationException ble)
|
||||||
|
{
|
||||||
|
ble.printStackTrace();
|
||||||
|
}
|
||||||
|
fireEvalEvent(eval);
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ fireEvalEvent() method
|
//{{{ fireEvalEvent() method
|
||||||
private void fireEvalEvent(String code)
|
public void fireEvalEvent(String code)
|
||||||
{
|
{
|
||||||
setCursor(WaitCursor);
|
setCursor(WaitCursor);
|
||||||
|
|
||||||
|
@ -150,26 +169,6 @@ public class FactorListener extends JTextPane
|
||||||
return (String)a.getAttribute(Link);
|
return (String)a.getAttribute(Link);
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ activateLink() method
|
|
||||||
private void activateLink(int pos)
|
|
||||||
{
|
|
||||||
String eval = getLinkAt(pos);
|
|
||||||
if(eval == null)
|
|
||||||
return;
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
StyledDocument doc = (StyledDocument)getDocument();
|
|
||||||
doc.insertString(doc.getLength(),eval + "\n",
|
|
||||||
getCharacterAttributes());
|
|
||||||
}
|
|
||||||
catch(BadLocationException ble)
|
|
||||||
{
|
|
||||||
ble.printStackTrace();
|
|
||||||
}
|
|
||||||
fireEvalEvent(eval);
|
|
||||||
} //}}}
|
|
||||||
|
|
||||||
//{{{ MouseHandler class
|
//{{{ MouseHandler class
|
||||||
class MouseHandler extends MouseInputAdapter
|
class MouseHandler extends MouseInputAdapter
|
||||||
{
|
{
|
||||||
|
@ -180,7 +179,7 @@ public class FactorListener extends JTextPane
|
||||||
Point pt = new Point(e.getX(), e.getY());
|
Point pt = new Point(e.getX(), e.getY());
|
||||||
int pos = editor.viewToModel(pt);
|
int pos = editor.viewToModel(pt);
|
||||||
if(pos >= 0)
|
if(pos >= 0)
|
||||||
activateLink(pos);
|
eval(getLinkAt(pos));
|
||||||
}
|
}
|
||||||
|
|
||||||
public void mouseMoved(MouseEvent e)
|
public void mouseMoved(MouseEvent e)
|
||||||
|
|
|
@ -71,25 +71,22 @@ public class FactorListenerPanel extends JPanel
|
||||||
listener = newListener()));
|
listener = newListener()));
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
|
//{{{ getListener() method
|
||||||
|
public FactorListener getListener()
|
||||||
|
{
|
||||||
|
return listener;
|
||||||
|
} //}}}
|
||||||
|
|
||||||
//{{{ newListener() method
|
//{{{ newListener() method
|
||||||
private FactorListener newListener()
|
private FactorListener newListener()
|
||||||
{
|
{
|
||||||
final FactorListener listener = new FactorListener();
|
final FactorListener listener = new FactorListener();
|
||||||
listener.addEvalListener(new EvalHandler());
|
listener.addEvalListener(new EvalHandler());
|
||||||
|
|
||||||
try
|
eval(new Cons(listener,
|
||||||
{
|
|
||||||
interp.call(new Cons(listener,
|
|
||||||
new Cons(interp.searchVocabulary(
|
new Cons(interp.searchVocabulary(
|
||||||
"listener","new-listener-hook"),
|
"listener","new-listener-hook"),
|
||||||
null)));
|
null)));
|
||||||
interp.run();
|
|
||||||
}
|
|
||||||
catch(Exception e)
|
|
||||||
{
|
|
||||||
System.err.println("Failed to initialize listener:");
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
|
|
||||||
return listener;
|
return listener;
|
||||||
} //}}}
|
} //}}}
|
||||||
|
@ -108,7 +105,7 @@ public class FactorListenerPanel extends JPanel
|
||||||
} //}}}
|
} //}}}
|
||||||
|
|
||||||
//{{{ eval() method
|
//{{{ eval() method
|
||||||
public void eval(Cons cmd)
|
private void eval(Cons cmd)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
|
|
|
@ -48,6 +48,8 @@ public class Def extends FactorParsingDefinition
|
||||||
{
|
{
|
||||||
// Read the word name
|
// Read the word name
|
||||||
FactorWord newWord = reader.nextWord(true);
|
FactorWord newWord = reader.nextWord(true);
|
||||||
|
newWord.line = reader.getScanner().getLineNumber();
|
||||||
|
newWord.file = reader.getScanner().getFileName();
|
||||||
reader.pushExclusiveState(word,newWord);
|
reader.pushExclusiveState(word,newWord);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -129,15 +129,13 @@ USE: strings
|
||||||
[ "top-level-continuation" set ] callcc0 ;
|
[ "top-level-continuation" set ] callcc0 ;
|
||||||
|
|
||||||
: init-interpreter ( -- )
|
: init-interpreter ( -- )
|
||||||
#! If we're run stand-alone, start the interpreter on stdio.
|
print-banner
|
||||||
"interactive" get [
|
room.
|
||||||
|
|
||||||
init-toplevel
|
init-toplevel
|
||||||
|
|
||||||
[
|
[
|
||||||
print-banner
|
|
||||||
room.
|
|
||||||
interpreter-loop
|
interpreter-loop
|
||||||
] [
|
] [
|
||||||
[ default-error-handler suspend ] when*
|
[ default-error-handler suspend ] when*
|
||||||
] catch
|
] catch ;
|
||||||
] when ;
|
|
||||||
|
|
|
@ -0,0 +1,115 @@
|
||||||
|
! :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: jedit
|
||||||
|
USE: arithmetic
|
||||||
|
USE: combinators
|
||||||
|
USE: namespaces
|
||||||
|
USE: stack
|
||||||
|
USE: strings
|
||||||
|
USE: vocabularies
|
||||||
|
|
||||||
|
: view ( -- view )
|
||||||
|
[ ] "org.gjt.sp.jedit.jEdit"
|
||||||
|
"getActiveView" jinvoke-static ;
|
||||||
|
|
||||||
|
: edit-pane ( -- editPane )
|
||||||
|
view
|
||||||
|
[ ] "org.gjt.sp.jedit.View" "getEditPane" jinvoke ;
|
||||||
|
|
||||||
|
: text-area ( -- textArea )
|
||||||
|
edit-pane
|
||||||
|
[ ] "org.gjt.sp.jedit.EditPane" "getTextArea" jinvoke ;
|
||||||
|
|
||||||
|
: text-area-buffer ( textArea -- buffer )
|
||||||
|
[ ] "org.gjt.sp.jedit.textarea.JEditTextArea"
|
||||||
|
"getBuffer" jinvoke ;
|
||||||
|
|
||||||
|
: buffer ( -- buffer )
|
||||||
|
edit-pane
|
||||||
|
[ ] "org.gjt.sp.jedit.EditPane" "getBuffer" jinvoke ;
|
||||||
|
|
||||||
|
: open-file* ( view parent path newFile props -- buffer )
|
||||||
|
[
|
||||||
|
"org.gjt.sp.jedit.View"
|
||||||
|
"java.lang.String"
|
||||||
|
"java.lang.String"
|
||||||
|
"boolean"
|
||||||
|
"java.util.Hashtable"
|
||||||
|
] "org.gjt.sp.jedit.jEdit" "openFile" jinvoke-static ;
|
||||||
|
|
||||||
|
: open-file ( parent path -- buffer )
|
||||||
|
view -rot f f open-file* ;
|
||||||
|
|
||||||
|
: wait-for-requests ( -- )
|
||||||
|
[ ]
|
||||||
|
"org.gjt.sp.jedit.io.VFSManager" "waitForRequests"
|
||||||
|
jinvoke-static ;
|
||||||
|
|
||||||
|
: line-count ( textarea -- lines )
|
||||||
|
[ ] "org.gjt.sp.jedit.textarea.JEditTextArea" "getLineCount"
|
||||||
|
jinvoke ;
|
||||||
|
|
||||||
|
: line>start-offset ( line textarea -- )
|
||||||
|
[ "int" ]
|
||||||
|
"org.gjt.sp.jedit.textarea.JEditTextArea"
|
||||||
|
"getLineStartOffset" jinvoke ;
|
||||||
|
|
||||||
|
: set-caret ( caret textarea -- )
|
||||||
|
[ "int" ]
|
||||||
|
"org.gjt.sp.jedit.textarea.JEditTextArea"
|
||||||
|
"setCaretPosition" jinvoke ;
|
||||||
|
|
||||||
|
: goto-line* ( line textarea -- )
|
||||||
|
tuck line>start-offset swap set-caret ;
|
||||||
|
|
||||||
|
: goto-line ( line textarea -- )
|
||||||
|
tuck line-count min swap goto-line* ;
|
||||||
|
|
||||||
|
: open-line/file ( line dir file -- )
|
||||||
|
open-file [
|
||||||
|
wait-for-requests text-area goto-line
|
||||||
|
] [
|
||||||
|
drop
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: resource-path ( -- path )
|
||||||
|
global [ "resource-path" get ] bind [ "." ] unless* ;
|
||||||
|
|
||||||
|
: word-file ( path -- dir file )
|
||||||
|
dup "resource:/" str-head? dup [
|
||||||
|
nip resource-path swap
|
||||||
|
] [
|
||||||
|
swap ( f file )
|
||||||
|
] ifte ;
|
||||||
|
|
||||||
|
: word-line/file ( word -- line dir file )
|
||||||
|
#! Note that line numbers here start from 1
|
||||||
|
[ "line" get pred "file" get word-file ] bind ;
|
||||||
|
|
||||||
|
: jedit ( word -- )
|
||||||
|
intern word-line/file open-line/file ;
|
|
@ -93,7 +93,6 @@ USE: parser
|
||||||
"/library/platform/jvm/compiler.factor" run-resource ! compiler
|
"/library/platform/jvm/compiler.factor" run-resource ! compiler
|
||||||
"/library/platform/jvm/debugger.factor" run-resource ! debugger
|
"/library/platform/jvm/debugger.factor" run-resource ! debugger
|
||||||
"/library/debugger.factor" run-resource ! debugger
|
"/library/debugger.factor" run-resource ! debugger
|
||||||
"/library/platform/jvm/listener.factor" run-resource ! listener
|
|
||||||
"/library/test/test.factor" run-resource ! test
|
"/library/test/test.factor" run-resource ! test
|
||||||
"/library/platform/jvm/test.factor" run-resource ! test
|
"/library/platform/jvm/test.factor" run-resource ! test
|
||||||
"/library/ansi.factor" run-resource ! ansi
|
"/library/ansi.factor" run-resource ! ansi
|
||||||
|
@ -117,6 +116,10 @@ USE: parser
|
||||||
"/library/httpd/wiki-responder.factor" run-resource ! wiki-responder
|
"/library/httpd/wiki-responder.factor" run-resource ! wiki-responder
|
||||||
"/library/httpd/default-responders.factor" run-resource ! default-responders
|
"/library/httpd/default-responders.factor" run-resource ! default-responders
|
||||||
|
|
||||||
|
!!! jEdit integration.
|
||||||
|
"/library/jedit/jedit.factor" run-resource ! jedit
|
||||||
|
|
||||||
!!! Final initialization...
|
!!! Final initialization...
|
||||||
"/library/init.factor" run-resource ! init
|
"/library/init.factor" run-resource ! init
|
||||||
"/library/platform/jvm/init.factor" run-resource ! init
|
"/library/platform/jvm/init.factor" run-resource ! init
|
||||||
|
"/library/platform/jvm/listener.factor" run-resource ! listener
|
||||||
|
|
|
@ -25,9 +25,6 @@
|
||||||
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
! OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
|
||||||
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
! ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||||
|
|
||||||
!!! This script and the scripts it calls bootstrap a new
|
|
||||||
!!! object database.
|
|
||||||
|
|
||||||
!!! Minimum amount of words needed to be able to read other
|
!!! Minimum amount of words needed to be able to read other
|
||||||
!!! resources.
|
!!! resources.
|
||||||
|
|
||||||
|
@ -54,6 +51,13 @@ IN: streams
|
||||||
"java.lang.Class" "getResourceAsStream" jinvoke
|
"java.lang.Class" "getResourceAsStream" jinvoke
|
||||||
<ireader> <breader> ;
|
<ireader> <breader> ;
|
||||||
|
|
||||||
|
IN: strings
|
||||||
|
|
||||||
|
: cat2 ( str str -- str )
|
||||||
|
#! Concatenate two strings.
|
||||||
|
swap
|
||||||
|
[ "java.lang.String" ] "java.lang.String" "concat" jinvoke ;
|
||||||
|
|
||||||
IN: parser
|
IN: parser
|
||||||
|
|
||||||
: parse* ( parser -- list )
|
: parse* ( parser -- list )
|
||||||
|
@ -78,7 +82,7 @@ IN: parser
|
||||||
<parser> parse* ;
|
<parser> parse* ;
|
||||||
|
|
||||||
: parse-resource ( resource -- list )
|
: parse-resource ( resource -- list )
|
||||||
dup <rreader> parse-stream ;
|
dup <rreader> swap "resource:" swap cat2 swap parse-stream ;
|
||||||
|
|
||||||
: run-resource ( path -- )
|
: run-resource ( path -- )
|
||||||
#! Reads and runs a source file from a resource path.
|
#! Reads and runs a source file from a resource path.
|
||||||
|
|
|
@ -77,4 +77,4 @@ USE: strings
|
||||||
|
|
||||||
t "startup-done" set
|
t "startup-done" set
|
||||||
|
|
||||||
init-interpreter ;
|
"interactive" get [ init-interpreter ] when ;
|
||||||
|
|
|
@ -28,6 +28,7 @@
|
||||||
IN: listener
|
IN: listener
|
||||||
USE: combinators
|
USE: combinators
|
||||||
USE: continuations
|
USE: continuations
|
||||||
|
USE: init
|
||||||
USE: interpreter
|
USE: interpreter
|
||||||
USE: kernel
|
USE: kernel
|
||||||
USE: lists
|
USE: lists
|
||||||
|
@ -104,7 +105,7 @@ USE: unparser
|
||||||
"readLine" jinvoke ;
|
"readLine" jinvoke ;
|
||||||
|
|
||||||
: listener-readln ( -- line )
|
: listener-readln ( -- line )
|
||||||
reset-attrs [ listener-readln* suspend ] callcc1 ;
|
reset-attrs [ listener-readln* toplevel ] callcc1 ;
|
||||||
|
|
||||||
: listener-write-attr ( string -- )
|
: listener-write-attr ( string -- )
|
||||||
style>attribute-set "listener" get
|
style>attribute-set "listener" get
|
||||||
|
@ -148,7 +149,5 @@ USE: unparser
|
||||||
<namespace> [
|
<namespace> [
|
||||||
dup "listener" set
|
dup "listener" set
|
||||||
<listener-stream> "stdio" set
|
<listener-stream> "stdio" set
|
||||||
print-banner
|
init-interpreter
|
||||||
room.
|
|
||||||
interpreter-loop
|
|
||||||
] bind ;
|
] bind ;
|
||||||
|
|
|
@ -77,4 +77,4 @@ USE: unparser
|
||||||
|
|
||||||
run-user-init
|
run-user-init
|
||||||
|
|
||||||
init-interpreter ;
|
"interactive" get [ init-interpreter ] when ;
|
||||||
|
|
|
@ -31,6 +31,13 @@ USE: kernel
|
||||||
USE: logic
|
USE: logic
|
||||||
USE: stack
|
USE: stack
|
||||||
|
|
||||||
|
: cat2 ( "a" "b" -- "ab" )
|
||||||
|
swap
|
||||||
|
80 <sbuf>
|
||||||
|
dup >r sbuf-append r>
|
||||||
|
dup >r sbuf-append r>
|
||||||
|
sbuf>str ;
|
||||||
|
|
||||||
: letter? CHAR: a CHAR: z between? ;
|
: letter? CHAR: a CHAR: z between? ;
|
||||||
: LETTER? CHAR: A CHAR: Z between? ;
|
: LETTER? CHAR: A CHAR: Z between? ;
|
||||||
: digit? CHAR: 0 CHAR: 9 between? ;
|
: digit? CHAR: 0 CHAR: 9 between? ;
|
||||||
|
|
|
@ -45,13 +45,6 @@ USE: stack
|
||||||
! string.
|
! string.
|
||||||
80 <sbuf> swap [ [ over sbuf-append ] when* ] each sbuf>str ;
|
80 <sbuf> swap [ [ over sbuf-append ] when* ] each sbuf>str ;
|
||||||
|
|
||||||
: cat2 ( "a" "b" -- "ab" )
|
|
||||||
swap
|
|
||||||
80 <sbuf>
|
|
||||||
dup >r sbuf-append r>
|
|
||||||
dup >r sbuf-append r>
|
|
||||||
sbuf>str ;
|
|
||||||
|
|
||||||
: cat3 ( "a" "b" "c" -- "abc" )
|
: cat3 ( "a" "b" "c" -- "abc" )
|
||||||
[ ] cons cons cons cat ;
|
[ ] cons cons cons cat ;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue