4 个版本 (1 个稳定版本)
1.0.3 | 2023 年 7 月 4 日 |
---|---|
0.1.2 | 2023 年 7 月 4 日 |
0.1.0 | 2021 年 11 月 7 日 |
0.0.1 | 2021 年 8 月 9 日 |
#1509 在 开发工具
每月下载量 43 次
用于 user_doc-tests
48KB
915 行
- 原因:停止在多个地方定义文档。
- 方法:
user_doc
将标记的 Rust 文档注释复制到可运行时访问的常量。
属性 user_doc_fn 和推导 user_doc_item 宏从注释中捕获文档,并在运行时提供内容。
每个宏调用填充一个包含在构建过程中捕获的所有文档的 DocDict 的节点。在运行时,编译时生成的全局树副本通过 RwLock 可在 DOCS 中访问。
宏选项
以下辅助属性(对于 user_doc_item)/ 参数(对于 user_doc_fn)可以轻松配置这些宏:
- chapter_blurb:一个字符串字面量,将被添加到包含的章节中,以描述此文档。
- chapter_name:一个字符串字面量,命名此章节。
- chapter_name_slug:一个以逗号分隔的字符串字面量列表,命名章节路径。
- chapter_num:一个与章节编号相对应的整数字面量。
- chapter_num_slug:一个与章节路径相对应的整数字面量列表。
如何在函数定义中使用 user_doc_fn
假设函数 call_this_function
的文档应在运行时对用户可见。
#[user_doc_fn(
chapter_num_slug(1, 3, 5),
chapter_name_slug(
"A Slaying in Luton",
"The Trouble About Ipswich",
"All Along the Weary M-5 Motorway",
),
)]
/// The parenchyma isn't as stiff as usual. It looks almost floppy.
/// I stick out a hand to touch it. It sucks my fingertips forward.
/// When I pull my hand back, a hanging bridge of sap follows.
pub fn call_this_function() -> bool { true }
注释行(从 "The parenchyma" 到 "sap follows.")将被捕获并分配在具有编号/命名节点的树层次结构中的位置
-
- "卢顿的杀戮"
-
- "伊普斯威奇的麻烦"
-
- "在疲惫的M-5高速公路上"
所以,在运行时
doc_data::load_global_docs(
None, None
).expect("must load docs from path");
let docs = &*doc_data::DOCS;
let docs_read_lock = docs.read().expect("must get read guard on global docs");
assert_eq!(
docs_read_lock.get_entry_at_numeric_path(
&[1,3,5] // corresponds to the `chapter_num_slug` argument in the macro call
).expect("must find test entry").1,
" The parenchyma isn\\'t as stiff as usual. It looks almost floppy.\
\n I stick out a hand to touch it. It sucks my fingertips forward.\
\n When I pull my hand back, a hanging bridge of sap follows.",
);
文档注释已经插入到树结构中。哇。现在,它可以在运行时显示给用户。
如何在结构体或枚举定义上使用 user_doc_item
。
想象一下相同的用例,但这次,文档附加到了结构体或枚举定义上。
当与结构体或枚举一起工作时,外部属性注释不会被捕获。
#[derive(user_doc_item, Clone, Debug, PartialEq, Eq)]
/// This comment WILL NOT BE captured for user docs.
pub enum Idiot {
#[chapter_num(23)] // should be overriden by slug
#[chapter_num_slug(1, 3, 4)]
#[chapter_name("The House of Almond Blossoms")]
/// He took a look at the card I showed him. His brows scrunched up like he smelled something offensive.
/// Could he tell it was fake? Everyone sweats in heat like this. If they don't, it means they're about to keel over from dehydration anyway. Still, I felt like I was sweating more than usual.
/// We stood frozen for a moment. It seemed an eon. Then he mercifully broke the silence.
/// "I can't read those. I'm just supposed to stand here and not let anyone pass."
/// I considered. I didn't want to get him in trouble – he was clearly new. Still, it was me or him.
/// "Oh," I said as casually as I could, "It says you're to let me through. But don't let anyone else through after me. It says that too.""
Kid(u16),
}
let docs = &*user_doc::DOCS;
let docs_read_lock = docs.read().expect("must get read guard on global docs");
std::println!("docs_read_lock {:?} {:#?}", std::time::Instant::now(), *docs_read_lock );
assert_eq!(
docs_read_lock.get_entry_at_numeric_path(&
[1,3,4], // corresponds to the `chapter_num_slug` helper attribute in the macro call
).expect("must find test entry").0,
String::from("The House of Almond Blossoms"),
);
在这里,chapter_num_slug
辅助属性覆盖了 chapter_num
属性。
Slug风格的(数字或名称)属性和参数将始终具有优先权。
如何为使用 mdbook
准备 DocDict
要将在 "tests/scratch/src" 路径处的全局文档存储库扩展到层次结构,请执行以下操作
user_doc::load_global_docs(
None, None
).expect("must load docs from path");
let docs = &*user_doc::DOCS;
let docs_read_lock = docs.read().expect("must get read guard on global docs");
docs_read_lock.expand_into_mdbook_dirs_at_path(
DirectoryNamingScheme::ChapterName,
"tests/scratch/src",
).expect("must expand docs into dirs");
目录 tests/scratch/src
将填充与 mdbook 格式对应的文档。
如何在工作区项目中使用
在具有多个子项目的工作区中捕获文档数据时,只有一个全局文档捕获存储实例。因此,来自最后一个编译的子项目的文档通常会覆盖先前捕获的文档。
解决方案
只需使用 set_persistence_file_name
宏为每个捕获指定不同的文件名。然后,在运行时将提供的文件名传递给 load_global_docs
函数调用。
给定一个看起来像的项目树
some_workspace
└ sub_package_a
┕ src/lib.rs
└ sub_package_b
┕ src/lib.rs
- 在
sub_package_a/src/lib.rs
中调用set_persistence_file_name("docs_a_or_whatever")
。 - 在
sub_package_b/src/lib.rs
中调用set_persistence_file_name("docs_b_or_whatever")
。 - 在其他地方,加载来自两个包的文档到新的字典中
let mut dict_a = DocDict::default();
load_global_docs("docs_a_or_whatever", Some(&mut dict_a));
let mut dict_b = DocDict::default();
load_global_docs("docs_b_or_whatever", Some(&mut dict_b));
重要提示
这些宏使用临时目录从编译时到运行时持久化数据。
不要在这些宏捕获的文档注释中存储敏感信息(密钥、密码等)。
依赖项
~5MB
~96K SLoC