2024-10-21 22:27:06 +09:00
|
|
|
|
def hello := "world"
|
|
|
|
|
|
|
|
|
|
structure Config where
|
|
|
|
|
useASCII : Bool := false
|
2024-10-22 18:02:57 +09:00
|
|
|
|
printAll : Bool := false
|
2024-10-21 22:27:06 +09:00
|
|
|
|
currentPrefix : String := ""
|
|
|
|
|
|
2024-10-22 17:02:57 +09:00
|
|
|
|
abbrev ConfigIO (α : Type) : Type := ReaderT Config IO α
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
2024-10-22 17:02:57 +09:00
|
|
|
|
#check read
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
#print ConfigIO
|
|
|
|
|
#check (Monad ConfigIO)
|
2024-10-22 17:02:57 +09:00
|
|
|
|
#check MonadLift
|
|
|
|
|
#check MonadWithReader
|
|
|
|
|
#check outParam
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
def currentConfig : ConfigIO Config :=
|
|
|
|
|
fun cfg => pure cfg
|
|
|
|
|
|
|
|
|
|
def usage : String :=
|
|
|
|
|
"Usage: doug [--ascii]
|
|
|
|
|
Options:
|
2024-10-22 18:02:57 +09:00
|
|
|
|
\t--ascii\tUse ASCII characters to display the directry structure
|
|
|
|
|
\t-a\tShow hidden entries"
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
2024-10-22 18:02:57 +09:00
|
|
|
|
def configFromArgs (args : List String) : Option Config :=
|
|
|
|
|
let parse_arg cfg arg :=
|
|
|
|
|
match arg with
|
|
|
|
|
| "--ascii" => some {cfg with useASCII := true}
|
|
|
|
|
| "-a" => some {cfg with printAll := true}
|
|
|
|
|
| _ => none
|
|
|
|
|
args.foldlM parse_arg {}
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
inductive Entry where
|
|
|
|
|
| file : String → Entry
|
|
|
|
|
| dir : String → Entry
|
|
|
|
|
|
|
|
|
|
def toEntry (path : System.FilePath) : IO (Option Entry) := do
|
|
|
|
|
match path.components.getLast? with
|
|
|
|
|
| none => pure (some (.dir ""))
|
|
|
|
|
| some "." | some ".." => pure none
|
|
|
|
|
| some name =>
|
|
|
|
|
pure (some (if (← path.isDir) then .dir name else .file name))
|
|
|
|
|
|
|
|
|
|
def Config.preFile (cfg : Config) :=
|
|
|
|
|
if cfg.useASCII then "|--" else "├──"
|
|
|
|
|
|
|
|
|
|
def Config.preDir (cfg : Config) :=
|
|
|
|
|
if cfg.useASCII then "| " else "│ "
|
|
|
|
|
|
|
|
|
|
/--
|
|
|
|
|
Modify `cfg` on entering a directory.
|
|
|
|
|
-/
|
|
|
|
|
def Config.inDirectory (cfg : Config) : Config :=
|
|
|
|
|
{cfg with currentPrefix := cfg.preDir ++ " " ++ cfg.currentPrefix}
|
|
|
|
|
|
|
|
|
|
def showFileName (file : String) : ConfigIO Unit := do
|
2024-10-22 17:02:57 +09:00
|
|
|
|
IO.println s!"{(← read).currentPrefix}{(← read).preFile} {file}"
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
def showDirName (dir : String) : ConfigIO Unit := do
|
2024-10-22 17:02:57 +09:00
|
|
|
|
IO.println s!"{(← read).currentPrefix}{(← read).preDir} {dir}/"
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
def doList [Applicative f] : List α → (α → f Unit) → f Unit
|
|
|
|
|
| [], _ => pure ()
|
|
|
|
|
| x :: xs, action =>
|
|
|
|
|
action x *>
|
|
|
|
|
doList xs action
|
|
|
|
|
|
|
|
|
|
partial def dirTree (path : System.FilePath) : ConfigIO Unit := do
|
2024-10-22 17:02:57 +09:00
|
|
|
|
match ← toEntry path with
|
2024-10-21 22:27:06 +09:00
|
|
|
|
| none => pure ()
|
2024-10-22 18:02:57 +09:00
|
|
|
|
| some (.file name) =>
|
|
|
|
|
if ((← read).printAll) || !(name.startsWith ".") then
|
|
|
|
|
showFileName name
|
2024-10-21 22:27:06 +09:00
|
|
|
|
| some (.dir name) =>
|
2024-10-22 18:02:57 +09:00
|
|
|
|
if ((← read).printAll) || !(name.startsWith ".") then
|
|
|
|
|
showDirName name
|
|
|
|
|
let contents ← path.readDir
|
|
|
|
|
withReader (·.inDirectory)
|
|
|
|
|
(doList contents.toList fun d =>
|
|
|
|
|
dirTree d.path)
|
2024-10-21 22:27:06 +09:00
|
|
|
|
|
|
|
|
|
def main (args : List String) : IO UInt32 := do
|
|
|
|
|
match configFromArgs args with
|
|
|
|
|
| some config =>
|
|
|
|
|
(dirTree (← IO.currentDir)).run config
|
|
|
|
|
pure 0
|
|
|
|
|
| none =>
|
|
|
|
|
IO.eprintln s!"Didn't understand argument(s) {" ".intercalate args}\n"
|
|
|
|
|
IO.eprintln usage
|
|
|
|
|
pure 1
|
|
|
|
|
|