54 次重大发布

0.57.0 2024年4月25日
0.55.0 2023年3月19日
0.54.0 2023年3月19日
0.53.0 2022年5月9日
0.7.0 2020年11月29日

#32 in 编程语言

Download history 86/week @ 2024-04-19 56/week @ 2024-04-26 1/week @ 2024-05-03 2/week @ 2024-05-17 1/week @ 2024-05-24 3/week @ 2024-05-31 2/week @ 2024-06-07

3,216 次每月下载
用于 2 crates

MIT 许可证

255KB
8K SLoC

节点仓库

lib-ruby-parser 仓库共享构建脚本和元数据。

文档

基本 API

节点

AST 节点信息通过 Node/NodeField/NodeFieldType 类型表示,您可以调用 nodes 函数检索所有节点。每个已知的节点都有一个名称和字段列表(两者都有注释作为数据)

use lib_ruby_parser_nodes::{nodes, Node, NodeField, NodeFieldType};

let all_nodes = nodes();
assert_eq!(nodes().len(), 124);

let def_node: &Node = all_nodes
    .iter()
    .find(|node| node.camelcase_name == "Def")
    .unwrap();
assert_eq!(def_node.fields.len(), 8);

let expression_l_field: &NodeField = def_node
    .fields
    .iter()
    .find(|field| field.snakecase_name == "expression_l")
    .unwrap();
assert_eq!(expression_l_field.field_type, NodeFieldType::Loc);

消息

消息具有相同的 API,但使用 Message/MessageField/MessageFieldType 类型

use lib_ruby_parser_nodes::{messages, Message, MessageField, MessageFieldType};

let all_messages = messages();
assert_eq!(messages().len(), 90);

let nth_ref_is_too_big_message: &Message = all_messages
    .iter().find(|message| message.camelcase_name == "NthRefIsTooBig").unwrap();
assert_eq!(nth_ref_is_too_big_message.fields.len(), 1);

let nth_ref_field: &MessageField = nth_ref_is_too_big_message
    .fields
    .iter()
    .find(|field| field.snakecase_name == "nth_ref")
    .unwrap();
assert_eq!(nth_ref_field.field_type, MessageFieldType::Str);

模板支持

此仓库主要用于其他仓库中的代码生成。有超过 100 个节点和 100 条消息,因此代码生成是处理它们的最佳方式。

Liquid 被用作主要的模板语言

use lib_ruby_parser_nodes::LiquidTemplate;

let template = LiquidTemplate::new_eval("
Nodes count: {{ nodes.size }}
Messages count: {{ messages.size }}
");
// Or LiquidTemplate::new("path/to/file.liquid")

assert_eq!(
    template.render().trim(),
    "Nodes count: 124\nMessages count: 90"
);

默认情况下,以下全局变量可用

  • nodes - 设置为 lib_ruby_parser_nodes::nodes()
  • messages - 设置为 lib_ruby_parser_nodes::messages()

可以在模板上调用 .with_global 来注册其他数据

use lib_ruby_parser_nodes::{
    LiquidTemplate,
    reexports::liquid::value,
};

let output = LiquidTemplate::new_eval("{{ custom_global }} bar")
    .with_global("custom_global", value!("foo"))
    .render();

assert_eq!(output, "foo bar")

默认情况下,以下过滤器可用

  • 所有默认 liquid 过滤器
  • | camelcase_to_snakecase - 将 FooBar 字符串转换为 foo_bar
  • | snakecase_to_camelcase - 将 foo_bar 字符串转换为 FooBar
  • | escape_c_keyword - 如果字符串是 C 关键字,则将其附加 _
  • | escape_cpp_keyword - 如果字符串是C++关键字,则将其附加到字符串中的 _
  • | escape_rust_keyword - 如果字符串是Rust关键字,则将其附加到字符串中的 _
  • | escape_js_keyword - 如果字符串是JavaScript关键字,则将其附加到字符串中的 _
  • | render_comment: "//", 4 - 将字符串数组(如 node.comment)渲染为字符串,其中每行前缀为 "//",并填充4个空格(除第一行外,第一行没有填充)

可以通过在模板上调用 .with_filter 来注册自定义过滤器

use liquid_core::{
    Result, Runtime, Value, ValueView,
    Display_filter, Filter, FilterReflection, ParseFilter,
};

#[derive(Clone, ParseFilter, FilterReflection)]
#[filter(
    name = "append_foo",
    description = "Appends 'foo' to a given string.",
    parsed(AppendFooFilter)
)]
pub struct AppendFoo;

#[derive(Debug, Default, Display_filter)]
#[name = "append_foo"]
struct AppendFooFilter;

impl Filter for AppendFooFilter {
    fn evaluate(&self, input: &dyn ValueView, _runtime: &dyn Runtime) -> Result<Value> {
        let input = input.to_kstr();
        let output = format!("{}foo", input);
        Ok(Value::scalar(output))
    }
}

use lib_ruby_parser_nodes::LiquidTemplate;

let template = LiquidTemplate::new_eval("{{ 'data ' | append_foo }}")
    .with_filter(AppendFoo)
    .render();

assert_eq!(template, "data foo");

您还可以查看更复杂的过滤器(如 render_comment),以了解如何传递参数。

将代码生成脚本发布到 wasmer.io

  1. wasmer.toml 中更新版本
  2. cargo构建 --示例代码生成 --发布 --目标wasm32-wasi
  3. wasmer publish

发布后,可以使用以下方式执行

$ wasmer run \
    --mapdir /pwd:. \
    iliabylich/lib-ruby-parser-nodes -- \
    --template /pwd/template.liquid \
    --write-to /pwd/output.ext

依赖项

~6–8MB
~152K SLoC