-USING: help.markup help.syntax math strings ;
+USING: help.markup help.syntax io math strings ;
IN: interpolate
-HELP: ninterpolate
-{ $values { "str" string } { "n" integer } }
-{ $description "Assigns stack arguments to numbered variables for string interpolation." }
+HELP: interpolate.
+{ $values { "str" string } }
+{ $description "String interpolation using named variables and/or stack arguments, writing to the " { $link output-stream } "." }
{ $examples
- { $example "USING: interpolate ;" "\"Bob\" \"Alice\" \"Hi ${0}, it's ${1}.\" 2 ninterpolate" "Hi Bob, it's Alice." }
-}
-{ $see-also interpolate } ;
+ { $example
+ "USING: interpolate ;"
+ "\"Bob\" \"Alice\" \"Hi ${0}, it's ${1}.\" interpolate."
+ "Hi Bob, it's Alice."
+ }
+ { $example
+ "USING: interpolate namespaces ;"
+ "\"Fred\" \"name\" [ \"Hi ${name}\" interpolate. ] with-variable"
+ "Hi Fred"
+ }
+} ;
+
+HELP: interpolate
+{ $values { "str" string } { "newstr" string } }
+{ $description "String interpolation using named variables and/or stack arguments, captured as a " { $link string } "." } ;
+
+{ interpolate interpolate. } related-words
USING: interpolate io.streams.string namespaces tools.test locals ;
IN: interpolate.tests
-[ "Hello, Jane." ] [
+{ "A B" } [ "A" "B" "${0} ${1}" interpolate ] unit-test
+{ "B A" } [ "A" "B" "${1} ${0}" interpolate ] unit-test
+{ "C A" } [ "A" "B" "C" "${2} ${0}" interpolate ] unit-test
+
+{ "Hello, Jane." } [
"Jane" "name" set
- [ "Hello, ${name}." interpolate ] with-string-writer
+ "Hello, ${name}." interpolate
+] unit-test
+
+{ "Mr. John" } [
+ "John" "name" set
+ "Mr." "${0} ${name}" interpolate
] unit-test
-[ "Sup Dawg, we heard you liked rims, so we put rims on your rims so you can roll while you roll." ] [
+{ "Sup Dawg, we heard you liked rims, so we put rims on your rims so you can roll while you roll." } [
"Dawg" "name" set
"rims" "noun" set
"roll" "verb" set
- [ "Sup ${name}, we heard you liked ${noun}, so we put ${noun} on your ${noun} so you can ${verb} while you ${verb}." interpolate ] with-string-writer
+ "Sup ${name}, we heard you liked ${noun}, so we put ${noun} on your ${noun} so you can ${verb} while you ${verb}." interpolate
] unit-test
-[ "Oops, I accidentally the whole economy..." ] [
+{ "Oops, I accidentally the whole economy..." } [
[let
"economy" :> noun
- [ I[ Oops, I accidentally the whole ${noun}...]I ] with-string-writer
+ "accidentally" [ I[ Oops, I ${0} the whole ${noun}...]I ] with-string-writer
]
] unit-test
! Copyright (C) 2008, 2009 Slava Pestov.
! See http://factorcode.org/license.txt for BSD license.
-USING: accessors arrays fry hashtables io kernel macros make
-math.parser multiline namespaces present sequences
-sequences.generalizations splitting strings vocabs.parser ;
+USING: accessors fry generalizations io io.streams.string kernel
+locals macros make math math.order math.parser multiline
+namespaces present sequences splitting strings vocabs.parser ;
IN: interpolate
<PRIVATE
-TUPLE: interpolate-var name ;
+TUPLE: named-var name ;
-: (parse-interpolate) ( string -- )
+TUPLE: stack-var n ;
+
+: (parse-interpolate) ( str -- )
[
- "${" split1-slice [ >string , ] [
+ "${" split1-slice [
+ [ >string , ] unless-empty
+ ] [
[
"}" split1-slice
- [ >string interpolate-var boa , ]
+ [
+ >string dup string>number
+ [ stack-var boa ] [ named-var boa ] ?if ,
+ ]
[ (parse-interpolate) ] bi*
] when*
] bi*
] unless-empty ;
-: parse-interpolate ( string -- seq )
+: parse-interpolate ( str -- seq )
[ (parse-interpolate) ] { } make ;
-: (interpolate) ( string quot -- quot' )
- [ parse-interpolate ] dip '[
- dup interpolate-var?
- [ name>> @ '[ _ @ present write ] ]
- [ '[ _ write ] ]
- if
- ] map [ ] join ; inline
+: max-stack-var ( seq -- n/f )
+ f [
+ dup stack-var? [ n>> [ or ] keep max ] [ drop ] if
+ ] reduce ;
+
+:: interpolate-quot ( str quot -- quot' )
+ str parse-interpolate :> args
+ args max-stack-var :> vars
+
+ args [
+ dup named-var? [
+ name>> quot call '[ _ @ present write ]
+ ] [
+ dup stack-var? [
+ n>> vars swap - 1 + '[ _ npick present write ]
+ ] [
+ '[ _ write ]
+ ] if
+ ] if
+ ] map concat
+
+ vars [
+ 1 + '[ _ ndrop ] append
+ ] when* ; inline
PRIVATE>
-MACRO: interpolate ( string -- )
- [ [ get ] ] (interpolate) ;
+MACRO: interpolate. ( str -- )
+ [ [ get ] ] interpolate-quot ;
+
+: interpolate ( str -- newstr )
+ [ interpolate. ] with-string-writer ; inline
-: interpolate-locals ( string -- quot )
- [ search [ ] ] (interpolate) ;
+: interpolate-locals ( str -- quot )
+ [ dup search [ [ ] ] [ [ get ] ] ?if ] interpolate-quot ;
SYNTAX: I[
"]I" parse-multiline-string
interpolate-locals append! ;
-
-MACRO: ninterpolate ( str n -- quot )
- swap '[
- _ narray [ number>string swap 2array ] map-index
- >hashtable [ _ interpolate ] with-variables
- ] ;