HELP: interpolate
{ $values { "str" string } }
-{ $description "String interpolation using named variables and/or stack arguments, writing to the " { $link output-stream } ". Format directives from the " { $vocab-link "formatting" } " vocabulary can be used as well." }
+{ $description "String interpolation using named variables and/or stack arguments, writing to the " { $link output-stream } "." }
{ $notes "Stack arguments are numbered from the top of the stack, or provided anonymously by order of arguments." }
{ $examples
{ $example
"\"Mr.\" \"Anderson\"" "\"Hello, ${} ${}\" interpolate"
"Hello, Mr. Anderson"
}
- { $example
- "USING: interpolate ;"
- "1.2345 \"${:011.5f}\" interpolate"
- "00001.23450"
- }
} ;
HELP: interpolate>string
! Copyright (C) 2008 Slava Pestov.
! See https://factorcode.org/license.txt for BSD license.
-USING: formatting interpolate io.streams.string namespaces tools.test ;
+USING: interpolate io.streams.string namespaces tools.test locals ;
{ "A B" } [ "A" "B" "${1} ${0}" interpolate>string ] unit-test
{ "B A" } [ "A" "B" "${0} ${1}" interpolate>string ] unit-test
] unit-test
{ "hello, world" } [ "world" I"hello, ${0}" ] unit-test
-
-{ "hello, ####world" } [ "world" I"hello, ${0:'#9s}" ] unit-test
-
-{ "0123.4500" } [ 123.45 I"${:09.4f}" ] unit-test
-
-[ I"${:ABCD}" ] [ unknown-format-directive? ] must-fail-with
! Copyright (C) 2008, 2009 Slava Pestov.
! See https://factorcode.org/license.txt for BSD license.
-USING: accessors arrays assocs combinators formatting
-formatting.private fry generalizations io io.streams.string
-kernel make math math.order math.parser multiline namespaces
-present quotations sequences splitting strings strings.parser
-vocabs.parser ;
+USING: accessors fry generalizations io io.streams.string kernel
+make math math.order math.parser multiline namespaces present
+sequences splitting strings strings.parser vocabs.parser ;
IN: interpolate
<PRIVATE
: (parse-interpolate) ( str -- )
[
"${" split1-slice [
- [ >string [ ] 2array , ] unless-empty
+ [ >string , ] unless-empty
] [
[
"}" split1-slice
[
- >string ":" split1 [
- [ string>number ]
- [ 1 + stack-var boa ]
- [ [ anon-var new ] [ named-var boa ] if-empty ] ?if
- ] [
- [ [ present ] ] [ format-directive ] if-empty
- ] bi* 2array ,
+ >string
+ [ string>number ]
+ [ 1 + stack-var boa ]
+ [ [ anon-var new ] [ named-var boa ] if-empty ] ?if ,
]
[ (parse-interpolate) ] bi*
] when*
: deanonymize ( seq -- seq' )
0 over <reversed> [
- dup first anon-var? [
- [ 1 + dup stack-var boa ] dip second 2array
+ dup anon-var? [
+ drop 1 + dup stack-var boa
] when
] map! 2drop ;
: max-stack-var ( seq -- n/f )
f [
- first dup stack-var? [ n>> [ or ] keep max ] [ drop ] if
+ dup stack-var? [ n>> [ or ] keep max ] [ drop ] if
] reduce ;
:: (interpolate-quot) ( str quot -- quot' )
args max-stack-var :> vars
args [
- [
- {
- { [ dup named-var? ] [ name>> quot call '[ _ @ ] ] }
- { [ dup stack-var? ] [ n>> '[ _ npick ] ] }
- [ 1quotation ]
- } cond
- ] dip '[ @ @ write ]
- ] { } assoc>map concat
+ dup named-var? [
+ name>> quot call '[ _ @ present write ]
+ ] [
+ dup stack-var? [
+ n>> '[ _ npick present write ]
+ ] [
+ '[ _ write ]
+ ] if
+ ] if
+ ] map concat
vars [
'[ _ ndrop ] append