60 lines
1.7 KiB
Standard ML
60 lines
1.7 KiB
Standard ML
|
|
structure FileString =
|
||
|
|
struct
|
||
|
|
fun findLastChr (str, pos, findChr) =
|
||
|
|
if pos < 0 then ~1
|
||
|
|
else if String.sub (str, pos) = findChr then pos
|
||
|
|
else findLastChr (str, pos - 1, findChr)
|
||
|
|
|
||
|
|
fun extractFileName str =
|
||
|
|
let
|
||
|
|
val lastSlash = findLastChr (str, String.size str - 1, #"/")
|
||
|
|
val strStart = lastSlash + 1
|
||
|
|
in
|
||
|
|
if lastSlash = ~1 then str
|
||
|
|
else String.substring (str, strStart, String.size str - strStart)
|
||
|
|
end
|
||
|
|
|
||
|
|
fun removeFileExtension str =
|
||
|
|
let val lastDot = findLastChr (str, String.size str - 1, #".")
|
||
|
|
in if lastDot = ~1 then str else String.substring (str, 0, lastDot)
|
||
|
|
end
|
||
|
|
|
||
|
|
local
|
||
|
|
fun finish acc =
|
||
|
|
let val acc = List.rev acc
|
||
|
|
in String.implode acc
|
||
|
|
end
|
||
|
|
|
||
|
|
(* convert from kebab-case or snake_case to PascalCase *)
|
||
|
|
fun loop (#"-" :: chr :: tl, acc) =
|
||
|
|
let val acc = Char.toUpper chr :: acc
|
||
|
|
in loop (tl, acc)
|
||
|
|
end
|
||
|
|
| loop (#"_" :: chr :: tl, acc) =
|
||
|
|
let val acc = Char.toUpper chr :: acc
|
||
|
|
in loop (tl, acc)
|
||
|
|
end
|
||
|
|
| loop ([#"-"], acc) = finish acc
|
||
|
|
| loop ([#"_"], acc) = finish acc
|
||
|
|
| loop (chr :: tl, acc) =
|
||
|
|
loop (tl, chr :: acc)
|
||
|
|
| loop ([], acc) = finish acc
|
||
|
|
in
|
||
|
|
fun filenameToStructureName str =
|
||
|
|
let
|
||
|
|
val str = removeFileExtension str
|
||
|
|
val str = extractFileName str
|
||
|
|
in
|
||
|
|
(* capitalise first character in string *)
|
||
|
|
case String.explode str of
|
||
|
|
chr :: tl => let val chr = Char.toUpper chr in loop (tl, [chr]) end
|
||
|
|
| [] => ""
|
||
|
|
end
|
||
|
|
end
|
||
|
|
|
||
|
|
fun getCollisionFilename str =
|
||
|
|
let val str = removeFileExtension str
|
||
|
|
in str ^ "-collisions.sml"
|
||
|
|
end
|
||
|
|
end
|