interpolate: allow mixing of named variables and stack arguments.

db4
John Benediktsson 2015-04-18 17:18:37 -07:00
parent 1ce1e2d27e
commit ce491a5aa1
3 changed files with 82 additions and 38 deletions

View File

@ -1,10 +1,24 @@
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." }
{ $example
"USING: interpolate ;"
"\"Bob\" \"Alice\" \"Hi ${0}, it's ${1}.\" interpolate."
"Hi Bob, it's Alice."
}
{ $see-also interpolate } ;
{ $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

View File

@ -3,21 +3,30 @@
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
[ "Sup Dawg, we heard you liked rims, so we put rims on your rims so you can roll while you roll." ] [
{ "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." } [
"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

View File

@ -1,50 +1,71 @@
! 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-locals ( string -- quot )
[ search [ ] ] (interpolate) ;
: interpolate ( str -- newstr )
[ interpolate. ] with-string-writer ; inline
: 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
] ;