glob

A glob library for MoonBit, supporting wildcard pattern matching on file paths.

glob
path
wildcard
pattern
matching
moon add justjavac/glob@0.1.8
Download zip
Author
Version
0.1.8
License
MIT
Last updated
2 months ago
Downloads
345
README

#Glob

ci coverage

A small path-aware glob matcher for MoonBit.

It supports ?, *, and **:

  • ? matches exactly one character
  • * matches inside a single path segment
  • ** matches across path separators

Bracket expressions such as [abc] are only validated by @glob.is_valid_pattern; they are not matched specially yet.

#Quick Start

///|
test {
assert_eq(@glob.glob("*.txt", "notes.txt"), true)
assert_eq(@glob.glob("src/*.mbt", "src/main.mbt"), true)
assert_eq(@glob.glob("src/*.mbt", "src/lib/main.mbt"), false)
assert_eq(@glob.glob("src/**/*.mbt", "src/lib/main.mbt"), true)
}

#Bulk Matching

///|
test {
let files = ["README.md", "src/main.mbt", "src/lib/util.mbt"]
assert_eq(@glob.glob_match_any("src/**", files), true)
assert_eq(@glob.glob_filter("src/**/*.mbt", files), ["src/lib/util.mbt"])
assert_eq(@glob.match_any_pattern(["*.md", "**/*.mbt"], "README.md"), true)
}

#Helpers

///|
test {
assert_eq(@glob.is_valid_pattern("[abc]*.txt"), true)
assert_eq(@glob.is_valid_pattern("[abc*.txt"), false)
assert_eq(@glob.escape_glob("file?.txt"), "file\\?.txt")
}

#
escape_glob

fn escape_glob(text : String) -> String

Prefix common glob metacharacters in text with backslashes.

This helper is useful when you want a readable escaped representation of a pattern fragment or when interoperating with tools that treat backslashes as escapes. The current matcher does not interpret backslashes specially.

Example

test {
assert_eq(@glob.escape_glob("file*.txt"), "file\\*.txt")
assert_eq(@glob.escape_glob("test?[1].log"), "test\\?\\[1\\].log")
assert_eq(@glob.escape_glob("plain.txt"), "plain.txt")
}

#
get_char

fn get_char(s : String, index : Int) -> Char?

Safely read one character from s by zero-based index.

This helper returns None instead of raising when the index is out of bounds.

Example

test {
assert_true(@glob.get_char("moon", 0) == Some('m'))
assert_true(@glob.get_char("moon", 3) == Some('n'))
assert_true(@glob.get_char("moon", 4) == None)
}

#
glob

fn glob(pattern : String, text : String) -> Bool raise

Match one glob pattern against one text path.

This is the main public entry point for the package.

Supported syntax:

  • * matches zero or more non-separator characters
  • ** matches zero or more characters, including separators
  • ? matches exactly one character

Bracket expressions such as [abc] are validated by is_valid_pattern, but they are not matched specially yet.

Example

test {
assert_eq(@glob.glob("file?.log", "file1.log"), true)
assert_eq(@glob.glob("**/*.md", "docs/api/readme.md"), true)
assert_eq(@glob.glob("*.jpg", "images/logo.png"), false)
}

#
glob_filter

fn glob_filter(pattern : String, paths : Array[String]) -> Array[String] raise

Return a new array containing only the paths that match pattern.

The original array is left unchanged.

Example

test {
let files = ["README.md", "src/main.mbt", "src/lib/util.mbt"]
assert_true(@glob.glob_filter("src/*.mbt", files) == ["src/main.mbt"])
assert_true(@glob.glob_filter("src/**/*.mbt", files) == ["src/lib/util.mbt"])
}

#
glob_match_any

fn glob_match_any(pattern : String, paths : Array[String]) -> Bool raise

Return whether any path in paths matches pattern.

The function stops at the first match.

Example

test {
let files = ["README.md", "src/main.mbt", "test/main_test.mbt"]
assert_eq(@glob.glob_match_any("**/*.mbt", files), true)
assert_eq(@glob.glob_match_any("**/*.rs", files), false)
}

#
is_path_separator

fn is_path_separator(c : Char) -> Bool

Return whether c is a supported path separator.

Both Unix (/) and Windows (\) separators are recognized.

Example

test {
assert_eq(@glob.is_path_separator('/'), true)
assert_eq(@glob.is_path_separator('\\'), true)
assert_eq(@glob.is_path_separator('a'), false)
}

#
is_valid_pattern

fn is_valid_pattern(pattern : String) -> Bool

Check whether pattern is structurally valid.

The current validation is intentionally small in scope: it only checks that [ and ] are balanced. It does not validate or implement the full glob grammar.

Example

test {
assert_eq(@glob.is_valid_pattern("*.mbt"), true)
assert_eq(@glob.is_valid_pattern("[abc]*.txt"), true)
assert_eq(@glob.is_valid_pattern("[abc*.txt"), false)
assert_eq(@glob.is_valid_pattern("abc]*.txt"), false)
}

#
match_any_pattern

fn match_any_pattern(patterns : Array[String], path : String) -> Bool raise

Return whether path matches at least one glob in patterns.

This is useful when several include rules should be checked together.

Example

test {
let patterns = ["*.md", "**/*.mbt"]
assert_eq(@glob.match_any_pattern(patterns, "README.md"), true)
assert_eq(@glob.match_any_pattern(patterns, "src/main.mbt"), true)
assert_eq(@glob.match_any_pattern(patterns, "package.json"), false)
}

#
match_char

fn match_char(pattern : Char, char : Char) -> Bool

Match one pattern character against one text character.

? matches any single character. All other characters must be equal.

Example

test {
assert_eq(@glob.match_char('a', 'a'), true)
assert_eq(@glob.match_char('?', 'x'), true)
assert_eq(@glob.match_char('a', 'b'), false)
}

#
match_here

fn match_here(pattern : String, text : String) -> Bool raise

Match pattern against text using the package's recursive glob rules.

This is the low-level matcher that powers glob. Most callers should use glob directly.

Matching rules:

  • ** can consume any suffix, including path separators
  • * can consume any suffix until the next path separator
  • ? matches exactly one character
  • every other character matches literally

Example

test {
assert_eq(@glob.match_here("**/*.mbt", "src/lib/main.mbt"), true)
assert_eq(@glob.match_here("*.mbt", "src/lib/main.mbt"), false)
}

Source Files

Powered by MoonBit

Site sourceReport issuePackagesBuild queueSkillsStatistics

© 2026 mooncakes.io