Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Release v2.9.20 #116

Merged
merged 14 commits into from
Jun 9, 2016
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
*.o
*.a
*.so
.DS_Store

# Folders
_obj
Expand Down
6 changes: 5 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -117,9 +117,13 @@ git clone https://github.com/qiniu/text.git qiniupkg.com/text

## 社区资源

### Embedded qlang (eql)

* [eql](app/eql): 全称 [embedded qlang](app/eql),是类似 erubis/erb 的东西。结合 go generate 可很方便地让 Go 支持模板(不是 html template,是指泛型)。

### 为 Go package 导出 qlang module

* [qexport](app/qexport/README.md): 可为 Go 语言的标准库或者你自己写的 Go Package 自动导出相应的 qlang module。
* [qexport](app/qexport): 可为 Go 语言的标准库或者你自己写的 Go Package 自动导出相应的 qlang module。

### Qlang Modules

Expand Down
3 changes: 1 addition & 2 deletions README_QL.md
Original file line number Diff line number Diff line change
Expand Up @@ -680,12 +680,11 @@ func (p *Bar) GetX() int {

```go
import (
"reflect"
"qlang.io/qlang.spec.v1"
)

var Exports = map[string]interface{}{
"Bar": qlang.NewType(reflect.TypeOf((*foo.Bar)(nil)).Elem()),
"Bar": qlang.StructOf((*foo.Bar)(nil)),
}
```

Expand Down
209 changes: 209 additions & 0 deletions app/eql/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,209 @@
Embedded qlang (eql)
========

eql 全称 embedded qlang,是类似 erubis/erb 的东西。结合 go generate 可很方便地让 Go 支持模板(不是 html template,是指语言特性中的泛型)。

## eql 程序

命令行:

```
eql <template_file> [-o <output_file>] [--key1=val1 --key2=val2 ...]
eql <template_dir> [-o <output_dir>] [--key1=val1 --key2=val2 ...]
```

其中

* `<template_file>`: 要解析的 eql 文件,也就是模板文件。
* `<template_dir>`: 要解析的 template package,也就是整个目录是一个模板。
* `<output_file>`: 要生成的渲染后的文件。如果没有指定则为 stdout。
* `<output_dir>`: 要生成的渲染后的目标目录。如果没有指定则为对 `<template_dir>` 进行渲染后的值。
* `--key1=val1 --key2=val2 ...`: 渲染涉及到的模板变量的值。

## 样例

### 单文件模板

* [example.eql](example.eql): 展示 eql 语法的样例,下文将详细介绍。

### 目录模板

* [$set.v1](example/$set.v1): 以集合类为例展示如何构建一个 template package。


## 语法

### 插入 qlang 代码

```
<%
// 在此插入 qlang 代码
%>
```

### 输出 qlang 表达式

```
<%= qlang_expr %>
```

你可以理解为这只是插入 qlang 代码的一种简写手法。它等价于:

```
<% print(qlang_expr) %>
```

### 输出一个变量

```
$var
```

你可以理解为这只是插入 qlang 代码的一种简写手法。它等价于:

```
<% print(var) %>
```

特别地,我们用 `$$` 表示普通字符 `$`。也就是说:

```
$$
```

等价于:

```
<% print('$') %>
```

## 用 eql 实现 Go 对泛型的支持

我们举例说明。假设我们现在实现了一个 Go 的模板类,文件名为 `example.eql`,内容如下:

```go
package eql_test

import (
<%= eql.imports(imports) %>
"encoding/binary"
)

// -----------------------------------------------------------------------------

type $module string

func (p $module) write(out $Writer, b []byte) {

_, err := out.Write(b)
if err != nil {
panic(err)
}
}

<% if Writer == "*bytes.Buffer" { %>
func (p $module) flush(out $Writer) {
}
<% } else { %>
func (p $module) flush(out $Writer) {

err := out.Flush()
if err != nil {
panic(err)
}
}
<% } %>

// -----------------------------------------------------------------------------
```

这个模板里面,有 3 个模板变量:

* `imports`: 需要额外引入的 package 列表,用 `,` 分隔。
* `module`: 模板类的类名。
* `Writer`: 模板类的用到的参数类型。

有了这个模板,我们就可以用如下命令生成具体的类:

```
eql example.eql -o example_bytes.go --imports=bytes --module=modbytes --Writer="*bytes.Buffer"
```

这会生成 example_bytes.go 文件,内容如下:

```go
package eql_test

import (
"bytes"
"encoding/binary"
)

// -----------------------------------------------------------------------------

type modbytes string

func (p modbytes) write(out *bytes.Buffer, b []byte) {

_, err := out.Write(b)
if err != nil {
panic(err)
}
}

func (p modbytes) flush(out *bytes.Buffer) {
}

// -----------------------------------------------------------------------------
```

再试试换一个 Writer:

```
eql example.eql -o example_bufio.go --imports=bufio --module=modbufio --Writer="*bufio.Writer"
```

我们得到 example_bufio.go,内容如下:

```go
package eql_test

import (
"bufio"
"encoding/binary"
)

// -----------------------------------------------------------------------------

type modbufio string

func (p modbufio) write(out *bufio.Writer, b []byte) {

_, err := out.Write(b)
if err != nil {
panic(err)
}
}

func (p modbufio) flush(out *bufio.Writer) {

err := out.Flush()
if err != nil {
panic(err)
}
}

// -----------------------------------------------------------------------------
```

### 结合 go generate

结合 go generate 工具,我们就可以很好地支持 Go 泛型了。

例如假设我们在 foo.go 里面引用了 Writer = `*bufio.Writer` 版本的实现,则只需要在 foo.go 文件中插入以下代码:

```go
//go:generate eql example.eql -o example_bufio.go --imports=bufio --module=module --Writer=*bufio.Writer
```

如此,你只需要在 foo.go 所在的目录执行 go generate 就可以生成 example_bufio.go 文件了。
Loading