From bc535f7b7169d9e0ef26faca108518f4005cc76c Mon Sep 17 00:00:00 2001 From: Martin Haug Date: Thu, 29 Dec 2022 11:49:01 +0100 Subject: [PATCH] `read` function --- library/src/compute/data.rs | 39 +++++++++++++++++++++++++++++++++++- library/src/lib.rs | 1 + tests/res/hello.txt | 1 + tests/res/invalid-utf8.txt | Bin 0 -> 70 bytes tests/typ/compute/data.typ | 15 +++++++++++++- 5 files changed, 54 insertions(+), 2 deletions(-) create mode 100644 tests/res/hello.txt create mode 100644 tests/res/invalid-utf8.txt diff --git a/library/src/compute/data.rs b/library/src/compute/data.rs index a018c09a6..a519e8e6e 100644 --- a/library/src/compute/data.rs +++ b/library/src/compute/data.rs @@ -4,6 +4,40 @@ use typst::diag::{format_xml_like_error, FileError}; use crate::prelude::*; +/// # Read file +/// Read plain text from a file. +/// +/// The file will be read and returned as a string. +/// +/// ## Example +/// ``` +/// #let text = read("data.html") +/// +/// An HTML file could look like this: +/// #raw(text, lang: "html") +/// ``` +/// +/// ## Parameters +/// - path: EcoString (positional, required) +/// Path to a file. +/// +/// - returns: EcoString +/// +/// ## Category +/// data-loading +#[func] +pub fn read(vm: &Vm, args: &mut Args) -> SourceResult { + let Spanned { v: path, span } = args.expect::>("path to file")?; + + let path = vm.locate(&path).at(span)?; + let data = vm.world().file(&path).at(span)?; + + let text = String::from_utf8(data.to_vec()) + .map_err(|_| "file is not valid utf-8") + .at(span)?; + Ok(Value::Str(text.into())) +} + /// # CSV /// Read structured data from a CSV file. /// @@ -184,7 +218,10 @@ fn convert_json(value: serde_json::Value) -> Value { /// Format the user-facing JSON error message. fn format_json_error(error: serde_json::Error) -> String { assert!(error.is_syntax() || error.is_eof()); - format!("failed to parse json file: syntax error in line {}", error.line()) + format!( + "failed to parse json file: syntax error in line {}", + error.line() + ) } /// # XML diff --git a/library/src/lib.rs b/library/src/lib.rs index a4c6fc30e..e345bbeef 100644 --- a/library/src/lib.rs +++ b/library/src/lib.rs @@ -124,6 +124,7 @@ fn scope() -> Scope { std.def_func::("even"); std.def_func::("odd"); std.def_func::("mod"); + std.def_func::("read"); std.def_func::("csv"); std.def_func::("json"); std.def_func::("xml"); diff --git a/tests/res/hello.txt b/tests/res/hello.txt new file mode 100644 index 000000000..5dd01c177 --- /dev/null +++ b/tests/res/hello.txt @@ -0,0 +1 @@ +Hello, world! \ No newline at end of file diff --git a/tests/res/invalid-utf8.txt b/tests/res/invalid-utf8.txt new file mode 100644 index 0000000000000000000000000000000000000000..71308112150558cf42a7b12ef117f1a9c1eb7684 GIT binary patch literal 70 TcmezOpF!#WUj_wAFoO~RJoqF6 literal 0 HcmV?d00001 diff --git a/tests/typ/compute/data.typ b/tests/typ/compute/data.typ index c1def7d55..5a0f76c6b 100644 --- a/tests/typ/compute/data.typ +++ b/tests/typ/compute/data.typ @@ -1,6 +1,19 @@ -// Test reading structured data. +// Test reading structured data and files. // Ref: false +--- +// Test reading plain text files +#let data = read("../../res/hello.txt") +#test(data, "Hello, world!") + +--- +// Error: 18-41 file not found (searched at res/missing.txt) +#let data = read("../../res/missing.txt") + +--- +// Error: 18-46 file is not valid utf-8 +#let data = read("../../res/invalid-utf8.txt") + --- // Test reading CSV data. // Ref: true