aboutsummaryrefslogtreecommitdiff
path: root/stdlib/source/library/lux/world/file.lux
diff options
context:
space:
mode:
Diffstat (limited to 'stdlib/source/library/lux/world/file.lux')
-rw-r--r--stdlib/source/library/lux/world/file.lux1308
1 files changed, 654 insertions, 654 deletions
diff --git a/stdlib/source/library/lux/world/file.lux b/stdlib/source/library/lux/world/file.lux
index c2e799be8..63fa2e88b 100644
--- a/stdlib/source/library/lux/world/file.lux
+++ b/stdlib/source/library/lux/world/file.lux
@@ -25,8 +25,8 @@
["[0]" list ("[1]#[0]" functor)]
["[0]" dictionary {"+" Dictionary}]]]
["[0]" ffi
- (~~ (.for ["JavaScript" (~~ (.as_is ["[0]" node_js]))
- "{old}" (~~ (.as_is ["node_js" //control/thread]))]
+ (~~ (.for "JavaScript" (~~ (.as_is ["[0]" node_js]))
+ "{old}" (~~ (.as_is ["node_js" //control/thread]))
(~~ (.as_is))))]
[macro
["[0]" template]]
@@ -298,662 +298,662 @@
java/io/File::new
(java/io/File::renameTo (java/io/File::new (ffi.as_string destination)))))
)))]
- (for [@.old (as_is <for_jvm>)
- @.jvm (as_is <for_jvm>)
-
- @.js
- (as_is (ffi.import: Buffer
- "[1]::[0]"
- ("static" from [Binary] ..Buffer))
-
- (ffi.import: FileDescriptor
- "[1]::[0]")
-
- (ffi.import: Stats
- "[1]::[0]"
- (size ffi.Number)
- (mtimeMs ffi.Number)
- (isFile [] ffi.Boolean)
- (isDirectory [] ffi.Boolean))
-
- (ffi.import: FsConstants
- "[1]::[0]"
- (F_OK ffi.Number)
- (R_OK ffi.Number)
- (W_OK ffi.Number)
- (X_OK ffi.Number))
-
- (ffi.import: Error
- "[1]::[0]"
- (toString [] ffi.String))
-
- (template: (with_async <write> <type> <body>)
- [(template.with_locals [<read>]
- (let [[<read> <write>] (: [(Async <type>) (async.Resolver <type>)]
- (async.async []))]
- (exec
- <body>
- <read>)))])
-
- (ffi.import: Fs
- "[1]::[0]"
- (constants FsConstants)
- (readFile [ffi.String ffi.Function] Any)
- (appendFile [ffi.String Buffer ffi.Function] Any)
- (writeFile [ffi.String Buffer ffi.Function] Any)
- (stat [ffi.String ffi.Function] Any)
- (access [ffi.String ffi.Number ffi.Function] Any)
- (rename [ffi.String ffi.String ffi.Function] Any)
- (utimes [ffi.String ffi.Number ffi.Number ffi.Function] Any)
- (readdir [ffi.String ffi.Function] Any)
- (mkdir [ffi.String ffi.Function] Any)
- (unlink [ffi.String ffi.Function] Any)
- (rmdir [ffi.String ffi.Function] Any))
-
- (def: (any_callback write!)
- (-> (async.Resolver (Try Any)) ffi.Function)
- (<| (ffi.function (_ [error Error]) Any)
- io.run!
- write!
- (if (ffi.null? error)
- {try.#Success []}
- {try.#Failure (Error::toString error)})))
-
- (def: (value_callback write!)
- (All (_ a) (-> (async.Resolver (Try a)) ffi.Function))
- (<| (ffi.function (_ [error Error datum Any]) Any)
- io.run!
- write!
- (if (ffi.null? error)
- {try.#Success (:expected datum)}
- {try.#Failure (Error::toString error)})))
-
- (ffi.import: JsPath
- "[1]::[0]"
- (sep ffi.String))
-
- (def: .public default
- (Maybe (System Async))
- (do maybe.monad
- [node_fs (node_js.require "fs")
- node_path (node_js.require "path")
- .let [node_fs (:as ..Fs node_fs)
- js_separator (if ffi.on_node_js?
- (JsPath::sep (:as ..JsPath node_path))
- "/")]]
- (in (: (System Async)
- (`` (implementation
- (def: separator
- js_separator)
-
- (~~ (template [<name> <method>]
- [(def: (<name> path)
- (do async.monad
- [?stats (with_async write! (Try Stats)
- (Fs::stat path (..value_callback write!)
- node_fs))]
- (in (case ?stats
- {try.#Success stats}
- (<method> stats)
-
- {try.#Failure _}
- false))))]
-
- [file? Stats::isFile]
- [directory? Stats::isDirectory]
- ))
-
- (def: (make_directory path)
- (do async.monad
- [outcome (with_async write! (Try Any)
- (Fs::access path
- (|> node_fs Fs::constants FsConstants::F_OK)
- (..any_callback write!)
- node_fs))]
- (case outcome
- {try.#Success _}
- (in (exception.except ..cannot_make_directory [path]))
-
- {try.#Failure _}
- (with_async write! (Try Any)
- (Fs::mkdir path (..any_callback write!) node_fs)))))
-
- (~~ (template [<name> <method>]
- [(def: (<name> path)
- (do [! (try.with async.monad)]
- [subs (with_async write! (Try (Array ffi.String))
- (Fs::readdir path (..value_callback write!) node_fs))]
- (|> subs
- (array.list {.#None})
- (list#each (|>> (format path js_separator)))
- (monad.each ! (function (_ sub)
- (# ! each (|>> <method> [sub])
- (with_async write! (Try Stats)
- (Fs::stat sub (..value_callback write!) node_fs)))))
- (# ! each (|>> (list.only product.right)
- (list#each product.left))))))]
-
- [directory_files Stats::isFile]
- [sub_directories Stats::isDirectory]
- ))
-
- (def: (file_size path)
- (do (try.with async.monad)
- [stats (with_async write! (Try Stats)
- (Fs::stat path (..value_callback write!)
- node_fs))]
- (in (|> stats
- Stats::size
- f.nat))))
-
- (def: (last_modified path)
- (do (try.with async.monad)
- [stats (with_async write! (Try Stats)
- (Fs::stat path (..value_callback write!)
- node_fs))]
- (in (|> stats
- Stats::mtimeMs
- f.int
- duration.of_millis
- instant.absolute))))
-
- (def: (can_execute? path)
- (# async.monad each
- (|>> (case> {try.#Success _}
- true
-
- {try.#Failure _}
- false)
- {try.#Success})
+ (for @.old (as_is <for_jvm>)
+ @.jvm (as_is <for_jvm>)
+
+ @.js
+ (as_is (ffi.import: Buffer
+ "[1]::[0]"
+ ("static" from [Binary] ..Buffer))
+
+ (ffi.import: FileDescriptor
+ "[1]::[0]")
+
+ (ffi.import: Stats
+ "[1]::[0]"
+ (size ffi.Number)
+ (mtimeMs ffi.Number)
+ (isFile [] ffi.Boolean)
+ (isDirectory [] ffi.Boolean))
+
+ (ffi.import: FsConstants
+ "[1]::[0]"
+ (F_OK ffi.Number)
+ (R_OK ffi.Number)
+ (W_OK ffi.Number)
+ (X_OK ffi.Number))
+
+ (ffi.import: Error
+ "[1]::[0]"
+ (toString [] ffi.String))
+
+ (template: (with_async <write> <type> <body>)
+ [(template.with_locals [<read>]
+ (let [[<read> <write>] (: [(Async <type>) (async.Resolver <type>)]
+ (async.async []))]
+ (exec
+ <body>
+ <read>)))])
+
+ (ffi.import: Fs
+ "[1]::[0]"
+ (constants FsConstants)
+ (readFile [ffi.String ffi.Function] Any)
+ (appendFile [ffi.String Buffer ffi.Function] Any)
+ (writeFile [ffi.String Buffer ffi.Function] Any)
+ (stat [ffi.String ffi.Function] Any)
+ (access [ffi.String ffi.Number ffi.Function] Any)
+ (rename [ffi.String ffi.String ffi.Function] Any)
+ (utimes [ffi.String ffi.Number ffi.Number ffi.Function] Any)
+ (readdir [ffi.String ffi.Function] Any)
+ (mkdir [ffi.String ffi.Function] Any)
+ (unlink [ffi.String ffi.Function] Any)
+ (rmdir [ffi.String ffi.Function] Any))
+
+ (def: (any_callback write!)
+ (-> (async.Resolver (Try Any)) ffi.Function)
+ (<| (ffi.function (_ [error Error]) Any)
+ io.run!
+ write!
+ (if (ffi.null? error)
+ {try.#Success []}
+ {try.#Failure (Error::toString error)})))
+
+ (def: (value_callback write!)
+ (All (_ a) (-> (async.Resolver (Try a)) ffi.Function))
+ (<| (ffi.function (_ [error Error datum Any]) Any)
+ io.run!
+ write!
+ (if (ffi.null? error)
+ {try.#Success (:expected datum)}
+ {try.#Failure (Error::toString error)})))
+
+ (ffi.import: JsPath
+ "[1]::[0]"
+ (sep ffi.String))
+
+ (def: .public default
+ (Maybe (System Async))
+ (do maybe.monad
+ [node_fs (node_js.require "fs")
+ node_path (node_js.require "path")
+ .let [node_fs (:as ..Fs node_fs)
+ js_separator (if ffi.on_node_js?
+ (JsPath::sep (:as ..JsPath node_path))
+ "/")]]
+ (in (: (System Async)
+ (`` (implementation
+ (def: separator
+ js_separator)
+
+ (~~ (template [<name> <method>]
+ [(def: (<name> path)
+ (do async.monad
+ [?stats (with_async write! (Try Stats)
+ (Fs::stat path (..value_callback write!)
+ node_fs))]
+ (in (case ?stats
+ {try.#Success stats}
+ (<method> stats)
+
+ {try.#Failure _}
+ false))))]
+
+ [file? Stats::isFile]
+ [directory? Stats::isDirectory]
+ ))
+
+ (def: (make_directory path)
+ (do async.monad
+ [outcome (with_async write! (Try Any)
+ (Fs::access path
+ (|> node_fs Fs::constants FsConstants::F_OK)
+ (..any_callback write!)
+ node_fs))]
+ (case outcome
+ {try.#Success _}
+ (in (exception.except ..cannot_make_directory [path]))
+
+ {try.#Failure _}
(with_async write! (Try Any)
- (Fs::access path
- (|> node_fs Fs::constants FsConstants::X_OK)
- (..any_callback write!)
- node_fs))))
-
- (def: (read path)
- (with_async write! (Try Binary)
- (Fs::readFile path (..value_callback write!)
- node_fs)))
-
- (def: (delete path)
- (do (try.with async.monad)
- [stats (with_async write! (Try Stats)
- (Fs::stat path (..value_callback write!) node_fs))]
+ (Fs::mkdir path (..any_callback write!) node_fs)))))
+
+ (~~ (template [<name> <method>]
+ [(def: (<name> path)
+ (do [! (try.with async.monad)]
+ [subs (with_async write! (Try (Array ffi.String))
+ (Fs::readdir path (..value_callback write!) node_fs))]
+ (|> subs
+ (array.list {.#None})
+ (list#each (|>> (format path js_separator)))
+ (monad.each ! (function (_ sub)
+ (# ! each (|>> <method> [sub])
+ (with_async write! (Try Stats)
+ (Fs::stat sub (..value_callback write!) node_fs)))))
+ (# ! each (|>> (list.only product.right)
+ (list#each product.left))))))]
+
+ [directory_files Stats::isFile]
+ [sub_directories Stats::isDirectory]
+ ))
+
+ (def: (file_size path)
+ (do (try.with async.monad)
+ [stats (with_async write! (Try Stats)
+ (Fs::stat path (..value_callback write!)
+ node_fs))]
+ (in (|> stats
+ Stats::size
+ f.nat))))
+
+ (def: (last_modified path)
+ (do (try.with async.monad)
+ [stats (with_async write! (Try Stats)
+ (Fs::stat path (..value_callback write!)
+ node_fs))]
+ (in (|> stats
+ Stats::mtimeMs
+ f.int
+ duration.of_millis
+ instant.absolute))))
+
+ (def: (can_execute? path)
+ (# async.monad each
+ (|>> (case> {try.#Success _}
+ true
+
+ {try.#Failure _}
+ false)
+ {try.#Success})
(with_async write! (Try Any)
- (if (Stats::isFile stats)
- (Fs::unlink path (..any_callback write!) node_fs)
- (Fs::rmdir path (..any_callback write!) node_fs)))))
-
- (def: (modify time_stamp path)
- (with_async write! (Try Any)
- (let [when (|> time_stamp instant.relative duration.millis i.frac)]
- (Fs::utimes path when when (..any_callback write!)
+ (Fs::access path
+ (|> node_fs Fs::constants FsConstants::X_OK)
+ (..any_callback write!)
node_fs))))
- (~~ (template [<name> <method>]
- [(def: (<name> data path)
- (with_async write! (Try Any)
- (<method> path (Buffer::from data) (..any_callback write!)
- node_fs)))]
-
- [write Fs::writeFile]
- [append Fs::appendFile]
- ))
-
- (def: (move destination origin)
- (with_async write! (Try Any)
- (Fs::rename origin destination (..any_callback write!)
- node_fs))))))))))
-
- @.python
- (as_is (type: (Tuple/2 left right)
- (Primitive "python_tuple[2]" [left right]))
-
- (ffi.import: PyFile
- "[1]::[0]"
- (read [] "io" "try" Binary)
- (write [Binary] "io" "try" "?" Any)
- (close [] "io" "try" "?" Any))
-
- (ffi.import: (open [ffi.String ffi.String] "io" "try" PyFile))
- (ffi.import: (tuple [[ffi.Integer ffi.Integer]] (Tuple/2 ffi.Integer ffi.Integer)))
-
- (ffi.import: os
- "[1]::[0]"
- ("static" F_OK ffi.Integer)
- ("static" R_OK ffi.Integer)
- ("static" W_OK ffi.Integer)
- ("static" X_OK ffi.Integer)
-
- ("static" mkdir [ffi.String] "io" "try" "?" Any)
- ("static" access [ffi.String ffi.Integer] "io" "try" ffi.Boolean)
- ("static" remove [ffi.String] "io" "try" "?" Any)
- ("static" rmdir [ffi.String] "io" "try" "?" Any)
- ("static" rename [ffi.String ffi.String] "io" "try" "?" Any)
- ("static" utime [ffi.String (Tuple/2 ffi.Integer ffi.Integer)] "io" "try" "?" Any)
- ("static" listdir [ffi.String] "io" "try" (Array ffi.String)))
-
- (ffi.import: os/path
- "[1]::[0]"
- ("static" isfile [ffi.String] "io" "try" ffi.Boolean)
- ("static" isdir [ffi.String] "io" "try" ffi.Boolean)
- ("static" sep ffi.String)
- ("static" getsize [ffi.String] "io" "try" ffi.Integer)
- ("static" getmtime [ffi.String] "io" "try" ffi.Float))
-
- (def: python_separator
- (os/path::sep))
-
- (`` (implementation: .public default
- (System IO)
-
- (def: separator
- ..python_separator)
-
- (~~ (template [<name> <method>]
- [(def: <name>
- (|>> <method>
- (io#each (|>> (try.else false)))))]
-
- [file? os/path::isfile]
- [directory? os/path::isdir]
- ))
-
- (def: make_directory
- os::mkdir)
-
- (~~ (template [<name> <method>]
- [(def: (<name> path)
- (let [! (try.with io.monad)]
- (|> path
- os::listdir
- (# ! each (|>> (array.list {.#None})
- (list#each (|>> (format path ..python_separator)))
- (monad.each ! (function (_ sub)
- (# ! each (|>> [sub]) (<method> sub))))
- (# ! each (|>> (list.only product.right)
- (list#each product.left)))))
- (# ! conjoint))))]
-
- [directory_files os/path::isfile]
- [sub_directories os/path::isdir]
- ))
-
- (def: file_size
- (|>> os/path::getsize
- (# (try.with io.monad) each (|>> .nat))))
-
- (def: last_modified
- (|>> os/path::getmtime
- (# (try.with io.monad) each (|>> f.int
- (i.* +1,000)
- duration.of_millis
- instant.absolute))))
-
- (def: (can_execute? path)
- (os::access path (os::X_OK)))
-
- (def: (read path)
- (do (try.with io.monad)
- [file (..open path "rb")
- data (PyFile::read file)
- _ (PyFile::close file)]
- (in data)))
-
- (def: (delete path)
- (do (try.with io.monad)
- [? (os/path::isfile path)]
- (if ?
- (os::remove path)
- (os::rmdir path))))
-
- (def: (modify time_stamp path)
- (let [when (|> time_stamp instant.relative duration.millis (i./ +1,000))]
- (os::utime path (..tuple [when when]))))
-
- (~~ (template [<name> <mode>]
- [(def: (<name> data path)
- (do (try.with io.monad)
- [file (..open path <mode>)
- _ (PyFile::write data file)]
- (PyFile::close file)))]
-
- [write "w+b"]
- [append "ab"]
- ))
-
- (def: (move destination origin)
- (os::rename origin destination))
- )))
-
- @.ruby
- (as_is (ffi.import: Time
- "[1]::[0]"
- ("static" at [Frac] Time)
- (to_f [] Frac))
-
- (ffi.import: Stat
- "[1]::[0]"
- (executable? [] Bit)
- (size Int)
- (mtime [] Time))
-
- (ffi.import: File "as" RubyFile
- "[1]::[0]"
- ("static" SEPARATOR ffi.String)
- ("static" open [Path ffi.String] "io" "try" RubyFile)
- ("static" stat [Path] "io" "try" Stat)
- ("static" delete [Path] "io" "try" Int)
- ("static" file? [Path] "io" "try" Bit)
- ("static" directory? [Path] "io" "try" Bit)
- ("static" utime [Time Time Path] "io" "try" Int)
-
- (read [] "io" "try" Binary)
- (write [Binary] "io" "try" Int)
- (flush [] "io" "try" "?" Any)
- (close [] "io" "try" "?" Any))
-
- (ffi.import: Dir
- "[1]::[0]"
- ("static" open [Path] "io" "try" Dir)
-
- (children [] "io" "try" (Array Path))
- (close [] "io" "try" "?" Any))
-
- (ffi.import: "fileutils" FileUtils
- "[1]::[0]"
- ("static" move [Path Path] "io" "try" "?" Any)
- ("static" rmdir [Path] "io" "try" "?" Any)
- ("static" mkdir [Path] "io" "try" "?" Any))
-
- (def: ruby_separator
- Text
- (..RubyFile::SEPARATOR))
-
- (`` (implementation: .public default
- (System IO)
-
- (def: separator
- ..ruby_separator)
-
- (~~ (template [<name> <test>]
- [(def: <name>
- (|>> <test>
- (io#each (|>> (try.else false)))))]
-
- [file? RubyFile::file?]
- [directory? RubyFile::directory?]
- ))
-
- (def: make_directory
- FileUtils::mkdir)
-
- (~~ (template [<name> <test>]
- [(def: (<name> path)
- (do [! (try.with io.monad)]
- [self (Dir::open path)
- children (Dir::children self)
- output (loop [input (|> children
- (array.list {.#None})
- (list#each (|>> (format path ..ruby_separator))))
- output (: (List ..Path)
- (list))]
- (case input
- {.#End}
- (in output)
-
- {.#Item head tail}
- (do !
- [verdict (<test> head)]
- (again tail (if verdict
- {.#Item head output}
- output)))))
- _ (Dir::close self)]
- (in output)))]
-
- [directory_files RubyFile::file?]
- [sub_directories RubyFile::directory?]
- ))
-
- (~~ (template [<name> <pipeline>]
- [(def: <name>
- (let [! (try.with io.monad)]
- (|>> RubyFile::stat
- (# ! each (`` (|>> (~~ (template.spliced <pipeline>))))))))]
-
- [file_size [Stat::size .nat]]
- [last_modified [Stat::mtime
- Time::to_f
- (f.* +1,000.0)
- f.int
- duration.of_millis
- instant.absolute]]
- [can_execute? [Stat::executable?]]
- ))
-
- (def: (read path)
- (do (try.with io.monad)
- [file (RubyFile::open path "rb")
- data (RubyFile::read file)
- _ (RubyFile::close file)]
- (in data)))
-
- (def: (delete path)
- (do (try.with io.monad)
- [? (RubyFile::file? path)]
- (if ?
- (RubyFile::delete path)
- (FileUtils::rmdir path))))
-
- (def: (modify moment path)
- (let [moment (|> moment
- instant.relative
- duration.millis
- i.frac
- (f./ +1,000.0)
- Time::at)]
- (RubyFile::utime moment moment path)))
-
- (~~ (template [<mode> <name>]
- [(def: (<name> data path)
- (do [! (try.with io.monad)]
- [file (RubyFile::open path <mode>)
- data (RubyFile::write data file)
- _ (RubyFile::flush file)
- _ (RubyFile::close file)]
- (in [])))]
-
- ["wb" write]
- ["ab" append]
- ))
-
- (def: (move destination origin)
- (do (try.with io.monad)
- [_ (FileUtils::move origin destination)]
- (in [])))
- )))
-
- ... @.php
- ... (as_is (ffi.import: (FILE_APPEND Int))
- ... ... https://www.php.net/manual/en/dir.constants.php
- ... (ffi.import: (DIRECTORY_SEPARATOR ffi.String))
- ... ... https://www.php.net/manual/en/function.pack.php
- ... ... https://www.php.net/manual/en/function.unpack.php
- ... (ffi.import: (unpack [ffi.String ffi.String] Binary))
- ... ... https://www.php.net/manual/en/ref.filesystem.php
- ... ... https://www.php.net/manual/en/function.file-get-contents.php
- ... (ffi.import: (file_get_contents [Path] "io" "try" ffi.String))
- ... ... https://www.php.net/manual/en/function.file-put-contents.php
- ... (ffi.import: (file_put_contents [Path ffi.String Int] "io" "try" ffi.Integer))
- ... (ffi.import: (filemtime [Path] "io" "try" ffi.Integer))
- ... (ffi.import: (filesize [Path] "io" "try" ffi.Integer))
- ... (ffi.import: (is_executable [Path] "io" "try" ffi.Boolean))
- ... (ffi.import: (touch [Path ffi.Integer] "io" "try" ffi.Boolean))
- ... (ffi.import: (rename [Path Path] "io" "try" ffi.Boolean))
- ... (ffi.import: (unlink [Path] "io" "try" ffi.Boolean))
-
- ... ... https://www.php.net/manual/en/function.rmdir.php
- ... (ffi.import: (rmdir [Path] "io" "try" ffi.Boolean))
- ... ... https://www.php.net/manual/en/function.scandir.php
- ... (ffi.import: (scandir [Path] "io" "try" (Array Path)))
- ... ... https://www.php.net/manual/en/function.is-file.php
- ... (ffi.import: (is_file [Path] "io" "try" ffi.Boolean))
- ... ... https://www.php.net/manual/en/function.is-dir.php
- ... (ffi.import: (is_dir [Path] "io" "try" ffi.Boolean))
- ... ... https://www.php.net/manual/en/function.mkdir.php
- ... (ffi.import: (mkdir [Path] "io" "try" ffi.Boolean))
-
- ... (def: byte_array_format "C*")
- ... (def: default_separator (..DIRECTORY_SEPARATOR))
-
- ... (template [<name>]
- ... [(exception: .public (<name> [file Path])
- ... (exception.report
- ... ["Path" file]))]
-
- ... [cannot_write_to_file]
- ... )
-
- ... (`` (implementation: (file path)
- ... (-> Path (File IO))
-
- ... (~~ (template [<name> <mode>]
- ... [(def: (<name> data)
- ... (do [! (try.with io.monad)]
- ... [outcome (..file_put_contents [path ("php pack" ..byte_array_format data) <mode>])]
- ... (if (bit#= false (:as Bit outcome))
- ... (# io.monad in (exception.except ..cannot_write_to_file [path]))
- ... (in []))))]
-
- ... [over_write +0]
- ... [append (..FILE_APPEND)]
- ... ))
-
- ... (def: (content _)
- ... (do [! (try.with io.monad)]
- ... [data (..file_get_contents [path])]
- ... (if (bit#= false (:as Bit data))
- ... (# io.monad in (exception.except ..cannot_find_file [path]))
- ... (in (..unpack [..byte_array_format data])))))
-
- ... (def: path
- ... path)
-
- ... (~~ (template [<name> <ffi> <pipeline>]
- ... [(def: (<name> _)
- ... (do [! (try.with io.monad)]
- ... [value (<ffi> [path])]
- ... (if (bit#= false (:as Bit value))
- ... (# io.monad in (exception.except ..cannot_find_file [path]))
- ... (in (`` (|> value (~~ (template.spliced <pipeline>))))))))]
-
- ... [size ..filesize [.nat]]
- ... [last_modified ..filemtime [(i.* +1,000) duration.of_millis instant.absolute]]
- ... ))
-
- ... (def: (can_execute? _)
- ... (..is_executable [path]))
-
- ... (def: (modify moment)
- ... (do [! (try.with io.monad)]
- ... [verdict (..touch [path (|> moment instant.relative duration.millis (i./ +1,000))])]
- ... (if (bit#= false (:as Bit verdict))
- ... (# io.monad in (exception.except ..cannot_find_file [path]))
- ... (in []))))
-
- ... (def: (move destination)
- ... (do [! (try.with io.monad)]
- ... [verdict (..rename [path destination])]
- ... (if (bit#= false (:as Bit verdict))
- ... (# io.monad in (exception.except ..cannot_find_file [path]))
- ... (in (file destination)))))
-
- ... (def: (delete _)
- ... (do (try.with io.monad)
- ... [verdict (..unlink [path])]
- ... (if (bit#= false (:as Bit verdict))
- ... (# io.monad in (exception.except ..cannot_find_file [path]))
- ... (in []))))
- ... ))
-
- ... (`` (implementation: (directory path)
- ... (-> Path (Directory IO))
-
- ... (def: scope
- ... path)
-
- ... (~~ (template [<name> <test> <constructor> <capability>]
- ... [(def: (<name> _)
- ... (do [! (try.with io.monad)]
- ... [children (..scandir [path])]
- ... (loop [input (|> children
- ... (array.list {.#None})
- ... (list.only (function (_ child)
- ... (not (or (text#= "." child)
- ... (text#= ".." child))))))
- ... output (: (List (<capability> IO))
- ... (list))]
- ... (case input
- ... {.#End}
- ... (in output)
-
- ... {.#Item head tail}
- ... (do !
- ... [verdict (<test> head)]
- ... (if verdict
- ... (again tail {.#Item (<constructor> head) output})
- ... (again tail output)))))))]
-
- ... [files ..is_file ..file File]
- ... [directories ..is_dir directory Directory]
- ... ))
-
- ... (def: (discard _)
- ... (do (try.with io.monad)
- ... [verdict (..rmdir [path])]
- ... (if (bit#= false (:as Bit verdict))
- ... (# io.monad in (exception.except ..cannot_find_directory [path]))
- ... (in []))))
- ... ))
-
- ... (`` (implementation: .public default
- ... (System IO)
-
- ... (~~ (template [<name> <test> <constructor> <exception>]
- ... [(def: (<name> path)
- ... (do [! (try.with io.monad)]
- ... [verdict (<test> path)]
- ... (# io.monad in
- ... (if verdict
- ... {try.#Success (<constructor> path)}
- ... (exception.except <exception> [path])))))]
-
- ... [file ..is_file ..file ..cannot_find_file]
- ... [directory ..is_dir ..directory ..cannot_find_directory]
- ... ))
-
- ... (def: (make_file path)
- ... (do [! (try.with io.monad)]
- ... [verdict (..touch [path (|> instant.now io.run! instant.relative duration.millis (i./ +1,000))])]
- ... (# io.monad in
- ... (if verdict
- ... {try.#Success (..file path)}
- ... (exception.except ..cannot_make_file [path])))))
-
- ... (def: (make_directory path)
- ... (do [! (try.with io.monad)]
- ... [verdict (..mkdir path)]
- ... (# io.monad in
- ... (if verdict
- ... {try.#Success (..directory path)}
- ... (exception.except ..cannot_make_directory [path])))))
-
- ... (def: separator
- ... ..default_separator)
- ... ))
- ... )
- ]
+ (def: (read path)
+ (with_async write! (Try Binary)
+ (Fs::readFile path (..value_callback write!)
+ node_fs)))
+
+ (def: (delete path)
+ (do (try.with async.monad)
+ [stats (with_async write! (Try Stats)
+ (Fs::stat path (..value_callback write!) node_fs))]
+ (with_async write! (Try Any)
+ (if (Stats::isFile stats)
+ (Fs::unlink path (..any_callback write!) node_fs)
+ (Fs::rmdir path (..any_callback write!) node_fs)))))
+
+ (def: (modify time_stamp path)
+ (with_async write! (Try Any)
+ (let [when (|> time_stamp instant.relative duration.millis i.frac)]
+ (Fs::utimes path when when (..any_callback write!)
+ node_fs))))
+
+ (~~ (template [<name> <method>]
+ [(def: (<name> data path)
+ (with_async write! (Try Any)
+ (<method> path (Buffer::from data) (..any_callback write!)
+ node_fs)))]
+
+ [write Fs::writeFile]
+ [append Fs::appendFile]
+ ))
+
+ (def: (move destination origin)
+ (with_async write! (Try Any)
+ (Fs::rename origin destination (..any_callback write!)
+ node_fs))))))))))
+
+ @.python
+ (as_is (type: (Tuple/2 left right)
+ (Primitive "python_tuple[2]" [left right]))
+
+ (ffi.import: PyFile
+ "[1]::[0]"
+ (read [] "io" "try" Binary)
+ (write [Binary] "io" "try" "?" Any)
+ (close [] "io" "try" "?" Any))
+
+ (ffi.import: (open [ffi.String ffi.String] "io" "try" PyFile))
+ (ffi.import: (tuple [[ffi.Integer ffi.Integer]] (Tuple/2 ffi.Integer ffi.Integer)))
+
+ (ffi.import: os
+ "[1]::[0]"
+ ("static" F_OK ffi.Integer)
+ ("static" R_OK ffi.Integer)
+ ("static" W_OK ffi.Integer)
+ ("static" X_OK ffi.Integer)
+
+ ("static" mkdir [ffi.String] "io" "try" "?" Any)
+ ("static" access [ffi.String ffi.Integer] "io" "try" ffi.Boolean)
+ ("static" remove [ffi.String] "io" "try" "?" Any)
+ ("static" rmdir [ffi.String] "io" "try" "?" Any)
+ ("static" rename [ffi.String ffi.String] "io" "try" "?" Any)
+ ("static" utime [ffi.String (Tuple/2 ffi.Integer ffi.Integer)] "io" "try" "?" Any)
+ ("static" listdir [ffi.String] "io" "try" (Array ffi.String)))
+
+ (ffi.import: os/path
+ "[1]::[0]"
+ ("static" isfile [ffi.String] "io" "try" ffi.Boolean)
+ ("static" isdir [ffi.String] "io" "try" ffi.Boolean)
+ ("static" sep ffi.String)
+ ("static" getsize [ffi.String] "io" "try" ffi.Integer)
+ ("static" getmtime [ffi.String] "io" "try" ffi.Float))
+
+ (def: python_separator
+ (os/path::sep))
+
+ (`` (implementation: .public default
+ (System IO)
+
+ (def: separator
+ ..python_separator)
+
+ (~~ (template [<name> <method>]
+ [(def: <name>
+ (|>> <method>
+ (io#each (|>> (try.else false)))))]
+
+ [file? os/path::isfile]
+ [directory? os/path::isdir]
+ ))
+
+ (def: make_directory
+ os::mkdir)
+
+ (~~ (template [<name> <method>]
+ [(def: (<name> path)
+ (let [! (try.with io.monad)]
+ (|> path
+ os::listdir
+ (# ! each (|>> (array.list {.#None})
+ (list#each (|>> (format path ..python_separator)))
+ (monad.each ! (function (_ sub)
+ (# ! each (|>> [sub]) (<method> sub))))
+ (# ! each (|>> (list.only product.right)
+ (list#each product.left)))))
+ (# ! conjoint))))]
+
+ [directory_files os/path::isfile]
+ [sub_directories os/path::isdir]
+ ))
+
+ (def: file_size
+ (|>> os/path::getsize
+ (# (try.with io.monad) each (|>> .nat))))
+
+ (def: last_modified
+ (|>> os/path::getmtime
+ (# (try.with io.monad) each (|>> f.int
+ (i.* +1,000)
+ duration.of_millis
+ instant.absolute))))
+
+ (def: (can_execute? path)
+ (os::access path (os::X_OK)))
+
+ (def: (read path)
+ (do (try.with io.monad)
+ [file (..open path "rb")
+ data (PyFile::read file)
+ _ (PyFile::close file)]
+ (in data)))
+
+ (def: (delete path)
+ (do (try.with io.monad)
+ [? (os/path::isfile path)]
+ (if ?
+ (os::remove path)
+ (os::rmdir path))))
+
+ (def: (modify time_stamp path)
+ (let [when (|> time_stamp instant.relative duration.millis (i./ +1,000))]
+ (os::utime path (..tuple [when when]))))
+
+ (~~ (template [<name> <mode>]
+ [(def: (<name> data path)
+ (do (try.with io.monad)
+ [file (..open path <mode>)
+ _ (PyFile::write data file)]
+ (PyFile::close file)))]
+
+ [write "w+b"]
+ [append "ab"]
+ ))
+
+ (def: (move destination origin)
+ (os::rename origin destination))
+ )))
+
+ @.ruby
+ (as_is (ffi.import: Time
+ "[1]::[0]"
+ ("static" at [Frac] Time)
+ (to_f [] Frac))
+
+ (ffi.import: Stat
+ "[1]::[0]"
+ (executable? [] Bit)
+ (size Int)
+ (mtime [] Time))
+
+ (ffi.import: File "as" RubyFile
+ "[1]::[0]"
+ ("static" SEPARATOR ffi.String)
+ ("static" open [Path ffi.String] "io" "try" RubyFile)
+ ("static" stat [Path] "io" "try" Stat)
+ ("static" delete [Path] "io" "try" Int)
+ ("static" file? [Path] "io" "try" Bit)
+ ("static" directory? [Path] "io" "try" Bit)
+ ("static" utime [Time Time Path] "io" "try" Int)
+
+ (read [] "io" "try" Binary)
+ (write [Binary] "io" "try" Int)
+ (flush [] "io" "try" "?" Any)
+ (close [] "io" "try" "?" Any))
+
+ (ffi.import: Dir
+ "[1]::[0]"
+ ("static" open [Path] "io" "try" Dir)
+
+ (children [] "io" "try" (Array Path))
+ (close [] "io" "try" "?" Any))
+
+ (ffi.import: "fileutils" FileUtils
+ "[1]::[0]"
+ ("static" move [Path Path] "io" "try" "?" Any)
+ ("static" rmdir [Path] "io" "try" "?" Any)
+ ("static" mkdir [Path] "io" "try" "?" Any))
+
+ (def: ruby_separator
+ Text
+ (..RubyFile::SEPARATOR))
+
+ (`` (implementation: .public default
+ (System IO)
+
+ (def: separator
+ ..ruby_separator)
+
+ (~~ (template [<name> <test>]
+ [(def: <name>
+ (|>> <test>
+ (io#each (|>> (try.else false)))))]
+
+ [file? RubyFile::file?]
+ [directory? RubyFile::directory?]
+ ))
+
+ (def: make_directory
+ FileUtils::mkdir)
+
+ (~~ (template [<name> <test>]
+ [(def: (<name> path)
+ (do [! (try.with io.monad)]
+ [self (Dir::open path)
+ children (Dir::children self)
+ output (loop [input (|> children
+ (array.list {.#None})
+ (list#each (|>> (format path ..ruby_separator))))
+ output (: (List ..Path)
+ (list))]
+ (case input
+ {.#End}
+ (in output)
+
+ {.#Item head tail}
+ (do !
+ [verdict (<test> head)]
+ (again tail (if verdict
+ {.#Item head output}
+ output)))))
+ _ (Dir::close self)]
+ (in output)))]
+
+ [directory_files RubyFile::file?]
+ [sub_directories RubyFile::directory?]
+ ))
+
+ (~~ (template [<name> <pipeline>]
+ [(def: <name>
+ (let [! (try.with io.monad)]
+ (|>> RubyFile::stat
+ (# ! each (`` (|>> (~~ (template.spliced <pipeline>))))))))]
+
+ [file_size [Stat::size .nat]]
+ [last_modified [Stat::mtime
+ Time::to_f
+ (f.* +1,000.0)
+ f.int
+ duration.of_millis
+ instant.absolute]]
+ [can_execute? [Stat::executable?]]
+ ))
+
+ (def: (read path)
+ (do (try.with io.monad)
+ [file (RubyFile::open path "rb")
+ data (RubyFile::read file)
+ _ (RubyFile::close file)]
+ (in data)))
+
+ (def: (delete path)
+ (do (try.with io.monad)
+ [? (RubyFile::file? path)]
+ (if ?
+ (RubyFile::delete path)
+ (FileUtils::rmdir path))))
+
+ (def: (modify moment path)
+ (let [moment (|> moment
+ instant.relative
+ duration.millis
+ i.frac
+ (f./ +1,000.0)
+ Time::at)]
+ (RubyFile::utime moment moment path)))
+
+ (~~ (template [<mode> <name>]
+ [(def: (<name> data path)
+ (do [! (try.with io.monad)]
+ [file (RubyFile::open path <mode>)
+ data (RubyFile::write data file)
+ _ (RubyFile::flush file)
+ _ (RubyFile::close file)]
+ (in [])))]
+
+ ["wb" write]
+ ["ab" append]
+ ))
+
+ (def: (move destination origin)
+ (do (try.with io.monad)
+ [_ (FileUtils::move origin destination)]
+ (in [])))
+ )))
+
+ ... @.php
+ ... (as_is (ffi.import: (FILE_APPEND Int))
+ ... ... https://www.php.net/manual/en/dir.constants.php
+ ... (ffi.import: (DIRECTORY_SEPARATOR ffi.String))
+ ... ... https://www.php.net/manual/en/function.pack.php
+ ... ... https://www.php.net/manual/en/function.unpack.php
+ ... (ffi.import: (unpack [ffi.String ffi.String] Binary))
+ ... ... https://www.php.net/manual/en/ref.filesystem.php
+ ... ... https://www.php.net/manual/en/function.file-get-contents.php
+ ... (ffi.import: (file_get_contents [Path] "io" "try" ffi.String))
+ ... ... https://www.php.net/manual/en/function.file-put-contents.php
+ ... (ffi.import: (file_put_contents [Path ffi.String Int] "io" "try" ffi.Integer))
+ ... (ffi.import: (filemtime [Path] "io" "try" ffi.Integer))
+ ... (ffi.import: (filesize [Path] "io" "try" ffi.Integer))
+ ... (ffi.import: (is_executable [Path] "io" "try" ffi.Boolean))
+ ... (ffi.import: (touch [Path ffi.Integer] "io" "try" ffi.Boolean))
+ ... (ffi.import: (rename [Path Path] "io" "try" ffi.Boolean))
+ ... (ffi.import: (unlink [Path] "io" "try" ffi.Boolean))
+
+ ... ... https://www.php.net/manual/en/function.rmdir.php
+ ... (ffi.import: (rmdir [Path] "io" "try" ffi.Boolean))
+ ... ... https://www.php.net/manual/en/function.scandir.php
+ ... (ffi.import: (scandir [Path] "io" "try" (Array Path)))
+ ... ... https://www.php.net/manual/en/function.is-file.php
+ ... (ffi.import: (is_file [Path] "io" "try" ffi.Boolean))
+ ... ... https://www.php.net/manual/en/function.is-dir.php
+ ... (ffi.import: (is_dir [Path] "io" "try" ffi.Boolean))
+ ... ... https://www.php.net/manual/en/function.mkdir.php
+ ... (ffi.import: (mkdir [Path] "io" "try" ffi.Boolean))
+
+ ... (def: byte_array_format "C*")
+ ... (def: default_separator (..DIRECTORY_SEPARATOR))
+
+ ... (template [<name>]
+ ... [(exception: .public (<name> [file Path])
+ ... (exception.report
+ ... ["Path" file]))]
+
+ ... [cannot_write_to_file]
+ ... )
+
+ ... (`` (implementation: (file path)
+ ... (-> Path (File IO))
+
+ ... (~~ (template [<name> <mode>]
+ ... [(def: (<name> data)
+ ... (do [! (try.with io.monad)]
+ ... [outcome (..file_put_contents [path ("php pack" ..byte_array_format data) <mode>])]
+ ... (if (bit#= false (:as Bit outcome))
+ ... (# io.monad in (exception.except ..cannot_write_to_file [path]))
+ ... (in []))))]
+
+ ... [over_write +0]
+ ... [append (..FILE_APPEND)]
+ ... ))
+
+ ... (def: (content _)
+ ... (do [! (try.with io.monad)]
+ ... [data (..file_get_contents [path])]
+ ... (if (bit#= false (:as Bit data))
+ ... (# io.monad in (exception.except ..cannot_find_file [path]))
+ ... (in (..unpack [..byte_array_format data])))))
+
+ ... (def: path
+ ... path)
+
+ ... (~~ (template [<name> <ffi> <pipeline>]
+ ... [(def: (<name> _)
+ ... (do [! (try.with io.monad)]
+ ... [value (<ffi> [path])]
+ ... (if (bit#= false (:as Bit value))
+ ... (# io.monad in (exception.except ..cannot_find_file [path]))
+ ... (in (`` (|> value (~~ (template.spliced <pipeline>))))))))]
+
+ ... [size ..filesize [.nat]]
+ ... [last_modified ..filemtime [(i.* +1,000) duration.of_millis instant.absolute]]
+ ... ))
+
+ ... (def: (can_execute? _)
+ ... (..is_executable [path]))
+
+ ... (def: (modify moment)
+ ... (do [! (try.with io.monad)]
+ ... [verdict (..touch [path (|> moment instant.relative duration.millis (i./ +1,000))])]
+ ... (if (bit#= false (:as Bit verdict))
+ ... (# io.monad in (exception.except ..cannot_find_file [path]))
+ ... (in []))))
+
+ ... (def: (move destination)
+ ... (do [! (try.with io.monad)]
+ ... [verdict (..rename [path destination])]
+ ... (if (bit#= false (:as Bit verdict))
+ ... (# io.monad in (exception.except ..cannot_find_file [path]))
+ ... (in (file destination)))))
+
+ ... (def: (delete _)
+ ... (do (try.with io.monad)
+ ... [verdict (..unlink [path])]
+ ... (if (bit#= false (:as Bit verdict))
+ ... (# io.monad in (exception.except ..cannot_find_file [path]))
+ ... (in []))))
+ ... ))
+
+ ... (`` (implementation: (directory path)
+ ... (-> Path (Directory IO))
+
+ ... (def: scope
+ ... path)
+
+ ... (~~ (template [<name> <test> <constructor> <capability>]
+ ... [(def: (<name> _)
+ ... (do [! (try.with io.monad)]
+ ... [children (..scandir [path])]
+ ... (loop [input (|> children
+ ... (array.list {.#None})
+ ... (list.only (function (_ child)
+ ... (not (or (text#= "." child)
+ ... (text#= ".." child))))))
+ ... output (: (List (<capability> IO))
+ ... (list))]
+ ... (case input
+ ... {.#End}
+ ... (in output)
+
+ ... {.#Item head tail}
+ ... (do !
+ ... [verdict (<test> head)]
+ ... (if verdict
+ ... (again tail {.#Item (<constructor> head) output})
+ ... (again tail output)))))))]
+
+ ... [files ..is_file ..file File]
+ ... [directories ..is_dir directory Directory]
+ ... ))
+
+ ... (def: (discard _)
+ ... (do (try.with io.monad)
+ ... [verdict (..rmdir [path])]
+ ... (if (bit#= false (:as Bit verdict))
+ ... (# io.monad in (exception.except ..cannot_find_directory [path]))
+ ... (in []))))
+ ... ))
+
+ ... (`` (implementation: .public default
+ ... (System IO)
+
+ ... (~~ (template [<name> <test> <constructor> <exception>]
+ ... [(def: (<name> path)
+ ... (do [! (try.with io.monad)]
+ ... [verdict (<test> path)]
+ ... (# io.monad in
+ ... (if verdict
+ ... {try.#Success (<constructor> path)}
+ ... (exception.except <exception> [path])))))]
+
+ ... [file ..is_file ..file ..cannot_find_file]
+ ... [directory ..is_dir ..directory ..cannot_find_directory]
+ ... ))
+
+ ... (def: (make_file path)
+ ... (do [! (try.with io.monad)]
+ ... [verdict (..touch [path (|> instant.now io.run! instant.relative duration.millis (i./ +1,000))])]
+ ... (# io.monad in
+ ... (if verdict
+ ... {try.#Success (..file path)}
+ ... (exception.except ..cannot_make_file [path])))))
+
+ ... (def: (make_directory path)
+ ... (do [! (try.with io.monad)]
+ ... [verdict (..mkdir path)]
+ ... (# io.monad in
+ ... (if verdict
+ ... {try.#Success (..directory path)}
+ ... (exception.except ..cannot_make_directory [path])))))
+
+ ... (def: separator
+ ... ..default_separator)
+ ... ))
+ ... )
+
(as_is)))
(def: .public (exists? monad fs path)