基本语法
jpFun 把排版能力统一写成函数调用。你不需要为每种功能记一套语法,只要认识几种基本类型,并学会把它们作为参数传给函数即可。
函数的参数由下面六种基本类型组成:
| 类型 | 示例 | 用途 |
|---|---|---|
| 字符串 | "轻快地"、center | 文字、名称和选项 |
| 布尔值 | true、false | 开启或关闭某个选项 |
| 数字 | 100、0.7、-12 | 速度、拍号和其他数值 |
| 长度/尺寸 | 12px、0.8em | 字号、间距和页面尺寸;省略单位时默认为 px |
| 内容 | {1 2 3 4} | 把一段谱面作为一个整体传入函数 |
| 标签 | start、end | 引用谱面中已经标记的对象 |
字符串只能使用英文双引号。不会产生歧义时可以省略引号,因此 @text(轻快地) 和 @text("轻快地") 的效果相同。内容也可以在不产生歧义时省略花括号;一旦内容中有多个元素,最好明确写出 {}。
@text("稍快,有活力")@box({1 2 3 4})第一个字符串中的逗号如果没有引号,会被当作参数分隔符;第二个函数中的四个音符如果没有花括号,则会变成四个参数。引号或花括号的作用,正是告诉解析器这些字符属于同一个值。
函数调用采用 @函数名(参数) 的形式。函数名与左括号之间不能有空格,多个参数之间使用英文逗号分隔:
@tempo(100)@meter(4, 4)@text(轻快地, size=0.8em)前两例使用位置参数,参数含义由顺序决定。最后一例还使用了命名参数 size=0.8em,直接指出要修改哪个选项。位置参数必须写在命名参数之前;没有传入的参数会使用当前设置或函数默认值。
函数的参数也可以是另一个函数调用,这就是函数嵌套。例如下面两种写法会得到相同的减时音符:
@div(@note(1), 1)@div({@note(1)}, 1)这里的 @note(1) 先产生音符,再作为内容交给 @div 添加一条减时线。外层函数只关心收到的内容,不需要知道内容是由简写还是另一个函数产生的。
大多数函数会直接产生或改变谱面内容。例如 @note 产生音符,@text 产生文本,@div 缩短内容的时值。这类函数写在哪里,结果就出现在那里,并且可以继续嵌套:
@box({@text(引子) 1 2 3 4}, padding=0.2em)另一类是关系函数,它们连接相隔较远的对象,例如 @tie 画连音线、@beam 手工连接减时线。关系函数通过标签找到端点,因此不必把整段音乐塞进函数参数中:
1@start 2 3@end @tie(start, end)@start 和 @end 没有紧跟左括号,所以不是函数调用,而是标签。标签会绑定到它前面最近的可标注对象;关系函数中写 start、end,即可引用这两个对象。标签名后的空格很重要,否则后面的字符可能会被当作标签名的一部分。
语法糖:一种能力,两种写法
Section titled “语法糖:一种能力,两种写法”完整的函数调用统一、明确,但频繁输入会显得冗长。jpFun 因此为常用功能提供了简短记号,称为语法糖。它们只是更方便的写法,并没有引入另一套能力。
例如,1/ 与 @div(1, 1) 都表示一个八分音符;1 ^ 3 ^ 5 与 @up(1, 3, 5) 都表示共享时值的和弦。
1/ 2/ @div(3, 1) @div(4, 1) | 1 ^ 3 ^ 5 -花括号只划定内容范围,不会自动换行,也不会创建新声部。学习新功能时,可以先查看它完整的函数形式,再把常用写法记成语法糖。
% 会把从它开始到行末的内容变成注释。注释不会出现在乐谱中,适合记录排版意图:
1 2 3 4 | % 第一小节5 6 7 1'函数的完整参数及更多写法见函数速查。