Citrus
A template generator which complex file structures can be defined in a single Yaml File.
How To Use
- Create template file.
- Execute command.
Template File(yaml)
# define symbols.
# These are user-defined symbols.
text: ['a', 'g']
flag: ['b']
object:
c:
# Data Type can only be specified as text, flag, or text_array
x: 'text'
y: 'flag'
z: 'text_array'
text_array: ['d']
object_array:
e:
# Same as Object
x: 'text'
y: 'flag'
# z: 'text_array' Object array is also possible, but it is more complex and therefore not a suitable example.
fragment:
f: |
Fragment is like a little template.
You cannot call fragment within fragment.
Other symbols can be called, just like template.
{a}
{b}
{c.x}
{#for i in d join g}{i}{#for}
{#for i in e join g}{i.x.snake}{#for}
# constant user-defined symbols.
constant_text:
k: 'k text'
constant_text_array:
l: ['L', 'LL', 'LLL']
constant_flag:
m: true
q: false
constant_object:
n:
x: 'n.x text'
y: ['Y', 'YY', 'YYY']
z: true
# define template
template:
# folder
h:
# file (path -> h/sample.txt)
sample.txt: |
Write the contents of the file.
You can call the symbols defined above.
{a}
{a.snake}
{b}
{#true b}b flag is true{#true}
{c.x}
{c.x.pascal}
{c.y}
{#true c.y}c.y flag is true{#true}
{#for i in c.z join g}{i.constant}{#for}
{#for i in d join g}{i.camel}{#for}
{#for object in e join g}{object.x}:{object.y}{#for}
{f}
{k}
{#for i in l join g}{i}{#for}
{#true m}m constant flag is true{#true}
{n.x}
{#for i in n.y join g}{i}{#for}
{#true n.z}n.z is true{#true}
# empty folder
i:
# empty folder
j: null
# Frame cannot be nested.
# invalid example
# x(for a in b):
# y(for c in d): 'some text'
# for loop frame
o_{i.snake}(for i in l):
sample.txt: 'hello world {i}'
# if switch frame
p.txt(true m): 'm is true'
r.txt(true q): 'q is true'
Generate Command
User Defined Symbol can be passed to generate command.
However, Fragment Symbol cannot be passed.
citrus generate --a 'a string' -b --c "object --x 'c x string' -y --z 'c z string 1' 'c z string 2' 'c z string 3'" --d 'd string 1' 'd string 2' 'd string 3' --e "object --x 'e x string 1' -y" "object --x 'e x string 2' -y" "object --x 'e x string 3'" --g ',' --generateLocation './example' --generateMode overwrite --templateFileLocation './example' --templateFileName example.yaml
--generateMode can be set to complement, overwrite, or synchronize.
complement は一番安全なモードで、出力先に既に file が存在する場合、その file は出力を行いません.
overwrite は次に安全なモードで、出力先に既に file が存在する場合、上書きします.
synchronize は、--generateLocation で指定した folder の配下を(すでにいくつかの file が存在していても)すべて削除し、出力します.
Result
Output to --generateLocation.
Folder Structure
+--- h
| sample.txt
|
+--- i
|
+--- j
|
+--- o_l
| sample.txt
|
+--- o_ll
| sample.txt
|
+--- o_lll
| sample.txt
|
+--- p.txt
h/sample.txt Content
Write the contents of the file.
You can call the symbols defined above.
a string
a_string
true
b flag is true
c x string
CXString
true
c.y flag is true
C_Z_STRING_1,C_Z_STRING_2,C_Z_STRING_3
dString1,dString2,dString3
e x string 1:true,e x string 2:true,e x string 3:false
Fragment is like a little template.
You cannot call fragment within fragment.
Other symbols can be called, just like template.
a string
true
c x string
d string 1,d string 2,d string 3
e_x_string_1,e_x_string_2,e_x_string_3
k text
L,LL,LLL
m constant flag is true
n.x text
Y,YY,YYY
n.z is true
Syntax
Please convert <Abstract Value> to concrete value at runtime.
Accesser
period で区切られた連続する Symbol の集まり.
a
object.b
Text Accesser
Accessor ending with text symbol.
Flag Accesser
Accessor ending with flag symbol.
Object Accesser
Accessor ending with object symbol.
Array Accesser
Accessor ending with array symbol.
Text Array Accesser
Accessor ending with text array symbol.
Object Array Accesser
Accessor ending with object array symbol.
Change Case
{<Text Accesser>.<Change Case Keyword>}
Not Case Syntax Sugar
{<Text Accesser>} equals to {<Text Accesser>.not}
text: ['a', 'b']
template:
change_case.txt: |
{a.pascal}
{b}
{b.not}
citrus generate --a 'sample text' --b 'sample text 2' ...
SampleText
sample text 2
sample text 2
For Loop
{#for <User Defined Symbol> in <Array Accesser> join <Text Accesser>}...{#for}
ここでの <User Defined Symbol> は ... の中でのみ参照される 一時的な symbol を新たに定義します。
この一時的な User Defined Symbol も他のものと同じように 名前が一意である必要があります。
<Array Accesser> の要素の数だけ ... を繰り返します.
<Text Accesser> は繰り返されるそれぞれの出力の境目に出力されます.
text_array: ['a']
fragment:
commaAndSpace: ', '
template:
for_loop.txt: |
{#for i in a join commaAndSpace}{i}{#for}
citurs generate --a A AA AAA ...
A, AA, AAA
Define Text
{#define_text <User Defined Symbol>}...{#define_text}
Text Symbol is defined as having 「...」.
Usually used with For Loop syntax.
text_array: ['a']
template:
define_text.txt: |
{#define_text aNewLine}
{#define_text}{#for i in a join aNewLine}{i}{#for}
citrus generate --a A AA AAA ...
A
AA
AAA
Equality Comparison
Usually used with If Branches syntax.
text: ['a', 'b']
template:
equality_comparison.txt: |
{#true a == b}a equal b{#true}
citrus generate --a x --b x ...
a equal b
If Branches
{#<Boolean Keyword> <Flag Accesser or Equality Comparison>}...{#<Boolean Keyword>}
flag: ['a', 'b']
text: ['x', 'y', 'z']
template:
if_branches.txt: |
{#true a}a flag is true{#true}
{#true x == y}x equal y{#true}
{#true b}b flag is true{#true}
{#true x == z}x equal z{#true}
{#false a}a flag is false{#false}
{#false x == y}x not equal y{#false}
{#false b}b flag is false{#false}
{#false x == z}x not equal z{#false}
citrus generate -a --x X --y X --z Z ...
a flag is true
x equal y
b flag is false
x not equal z
Symbol
Symbol is variables and special word available in templates.
User Defined Symbol
Following, valid characters for user defined symbol. However, duplicate with Keyword is invalid.
-
a~z
-
A~Z
-
0~9
- However, invalid character as a prefix.
- invalid example: 2abc, 012d,
- valid example: a1c2, _01234,
-
_ (under bar)
Text Symbol
bind text.
Flag Symbol
bind boolean(true or false).
Object Symbol
bind text or text array or boolean at key value format.
Array Symbol
bind multiple data.
Text Array Symbol
bind multiple text.
Object Array Symbol
bind multiple object.
Fragment Symbol
bind text.
Keyword
keyword is built in symbol available in syntax.
- in
- join
Define Keyword
- define_text
- define_object
Block Type Keyword
- for
- protect
Boolean Keyword
- true
- false
Change Case Keyword
- camel (test string -> testString)
- capital (test string -> Test String)
- constant (test string -> TEST_STRING)
- dot (test string -> test.string)
- header (test string -> Test-String)
- no (TestString -> test string)
- not (test string -> test string)
- param (test string -> test-string)
- pascal (test string -> TestString)
- path (test string -> test/string)
- sentence (test string -> Test string)
- snake (test string -> test_string)
- swap (test string -> TEST STRING)