///|
const FileEntryCode =
#|pub enum FileEntry {
#| Dir(Map[String, FileEntry])
#| File(Bytes)
#|} derive(Show)
///|
fn main {
let dir = @ref.new("assets")
let output = @ref.new("assets.mbt")
let var_name = @ref.new("assets")
let is_pub = @ref.new(false)
let include_entry = @ref.new(false)
let argv = @sys.get_cli_args()
let usage = " usage: \{argv[0]} [options]"
@ArgParser.parse(
[
("--dir", "-d", Set_string(dir), "assets directory"),
("--output", "-o", Set_string(output), "output directory"),
("--var", "-v", Set_string(var_name), "variable name"),
("--pub", "-p", Set(is_pub), "make the variable public"),
("--include-entry", "-i", Set(include_entry), "include the entry point"),
],
ignore,
usage,
argv,
)
if dir.val == "" {
println("Error: directory is not specified")
return
}
let assets = scan_dir(dir.val)
let code = (if include_entry.val { "\{FileEntryCode}\n" } else { "" }) +
(if is_pub.val { "pub " } else { "" }) +
"let \{var_name.val}: FileEntry = \{assets.to_string()}"
if (try? @fs.write_string_to_file(output.val, code)) is Err(e) {
println("Error: failed to write output file: \{e}")
return
}
}
///|
fn scan_dir(dir : String) -> FileEntry {
let map = {}
if (try? @fs.read_dir(dir)) is Ok(list) {
for file_name in list {
let file_path = dir + "/" + file_name
if (try? @fs.is_dir(file_path)) is Ok(true) {
let submap = scan_dir(file_path)
map.set(file_name, submap)
} else if (try? @fs.read_file_to_bytes(file_path)) is Ok(data) {
map.set(file_name, File(data))
}
}
}
Dir(map)
}
///|
pub fn FileEntry::extract_dir(
self : FileEntry,
prefix? : String,
) -> Unit raise Failure {
if self is Dir(map) {
for file_name, value in map {
if value is Dir(_) {
value.extract_dir(prefix?=prefix.map(p => p + "/" + file_name))
} else if value is File(bytes) {
let file_path = prefix
.map(p => p + "/" + file_name)
.unwrap_or(file_name)
if (try? @fs.write_bytes_to_file(file_path, bytes)) is Err(e) {
raise Failure("failed to write file: \{e}")
}
}
}
} else {
raise Failure("not a directory")
}
}