Glob
Files found by glob patterns like docs/**/*.md, with patterns to leave out, and paths tested against patterns.
Version 1.0.0 · 3 functions · 2 crates
Functions
What use glob.qwer gives a program, with the types Quillo sees. To take only some, or under other names: use glob_files, glob_match from glob (Quillo 0.6).
glob_files(base: str, patterns: list, exclude: list) → listor an errorThe files under the folder base matching any of patterns, and none of exclude, as paths relative to base, sorted. * stays within a folder, ** crosses folders, ? is one character, {a,b} either, [abc] one of them. Links are not followed; at most 100,000 results.
glob_match(pattern: str, path: str) → boolor an errorWhether path matches the glob pattern, with the same rules: "src/**/*.rs" matches "src/a/b.rs" and "src/b.rs".
glob_filter(paths: list, patterns: list) → listor an errorThe paths (any text: names from a database, keys in a bucket) that match any of patterns, in their order.
Get it
$ quillo install glob # glob.qwer into this folder$ quillo install glob --example # and its example, glob.qweOr with curl:
$ curl -O https://quillolang.org/plugins/files/glob.qwer$ curl -O https://quillolang.org/plugins/files/glob.qweThen, in your program, all of it or only what you call:
use glob.qweruse glob_files, glob_match from glob // Quillo 0.6: only theseIt uses these crates, which cargo fetches the first time the plugin is built:
globset = "0.4"walkdir = "2"Example
// A docs site that finds its pages by pattern, and an asset list filtered the same way.//// quillo run glob.qwe then open http://localhost:8080/pagesuse "glob.qwer"fn seed() { write_file("data/site/docs/index.md", "# Docs") write_file("data/site/docs/guide/routes.md", "# Routes") write_file("data/site/docs/guide/drafts/next.md", "# Soon") write_file("data/site/docs/logo.png", "png") write_file("data/site/blog/hello.md", "# Hello")}route GET /pages { seed() glob_files("data/site", ["docs/**/*.md", "blog/*.md"], ["**/drafts/**"])}route GET /match = { nested: glob_match("docs/**/*.md", "docs/guide/routes.md")?, one_level: glob_match("docs/*.md", "docs/guide/routes.md")?, images: glob_filter(["a.jpg", "b.PNG", "c.png", "notes.txt"], ["*.{jpg,png}"])?,}$ quillo run glob.qwe$ curl 'localhost:8080/pages'$ curl 'localhost:8080/match'Source
//! Files found by glob patterns such as "docs/**/*.md" or "*.{jpg,png}", with patterns to leave out, and paths tested against patterns.//! version: 1.0.0//!//! [dependencies]//! globset = "0.4"//! walkdir = "2"const MAX_RESULTS: usize = 100_000;const MAX_SEEN: usize = 1_000_000;fn set(patterns: &[String]) -> Result<globset::GlobSet, String> { let mut b = globset::GlobSetBuilder::new(); for p in patterns { let g = globset::GlobBuilder::new(p.trim_start_matches("./")).literal_separator(true).backslash_escape(true).build().map_err(|e| format!("`{}`: {}", p, e))?; b.add(g); } b.build().map_err(|e| e.to_string())}/// The files under the folder `base` matching any of `patterns`, and none of `exclude`, as paths relative to `base`, sorted./// `*` stays within a folder, `**` crosses folders, `?` is one character, `{a,b}` either, `[abc]` one of them. Links are not followed; at most 100,000 results.pub fn glob_files(base: &str, patterns: Vec<String>, exclude: Vec<String>) -> Result<Vec<String>, String> { let root = std::path::Path::new(if base.is_empty() { "." } else { base }); if !root.is_dir() { return Err(format!("{}: not a folder", base)); } let want = set(&patterns)?; let skip = set(&exclude)?; let mut out = vec![]; for (seen, e) in walkdir::WalkDir::new(root).min_depth(1).follow_links(false).into_iter().filter_map(Result::ok).enumerate() { if seen > MAX_SEEN || out.len() >= MAX_RESULTS { break; } if !e.file_type().is_file() { continue; } let rel = e.path().strip_prefix(root).unwrap_or(e.path()).to_string_lossy().replace('\\', "/"); if want.is_match(&rel) && !skip.is_match(&rel) { out.push(rel); } } out.sort(); Ok(out)}/// Whether `path` matches the glob `pattern`, with the same rules: "src/**/*.rs" matches "src/a/b.rs" and "src/b.rs".pub fn glob_match(pattern: &str, path: &str) -> Result<bool, String> { Ok(set(&[pattern.to_string()])?.is_match(path.trim_start_matches("./")))}/// The `paths` (any text: names from a database, keys in a bucket) that match any of `patterns`, in their order.pub fn glob_filter(paths: Vec<String>, patterns: Vec<String>) -> Result<Vec<String>, String> { let s = set(&patterns)?; Ok(paths.into_iter().filter(|p| s.is_match(p.trim_start_matches("./"))).collect())}Related
file_tree.qwer · 1.0.0A folder's files, recursively, with sizes and dates: listings with limits, a folder's total size, and its largest and newest files.9 views · 6 downloads3D models models_3d.qwer · 1.0.0STL and OBJ models read: triangles, size, volume, surface area and whether the mesh is closed, a 3D-print quote by weight, and OBJ turned into binary STL.6 views · 7 downloads7-Zip sevenz.qwer · 1.0.07-Zip archives listed, one file read, opened safely into a folder, and made from a folder.7 views · 8 downloadsBrotli brotli.qwer · 1.0.0Brotli compression of files and text: smaller than gzip for HTML, CSS and JavaScript served pre-compressed.7 views · 9 downloadsbzip2 bzip2.qwer · 1.0.0bzip2 compression of files and text in pure Rust, .bz2 dumps unpacked, and their first lines read without unpacking them all.6 views · 7 downloadsDisk space disk_space.qwer · 1.0.0Free and total space of the disk a path is on, for health checks, refusing uploads before the disk fills, and admin pages.8 views · 8 downloadsThread 0 posts
On Glob: questions, tips, corrections, and code that uses it.
No posts yet. The first one opens the thread.