# <!-- rdoc-file=dir.rb -->
# Objects of class Dir are directory streams representing directories in the
# underlying file system. They provide a variety of ways to list directories and
# their contents. See also File.
#
# The directory used in these examples contains the two regular files
# (`config.h` and `main.rb`), the parent directory (`..`), and the directory
# itself (`.`).
#
# ## What's Here
#
# First, what's elsewhere. Class Dir:
#
# *   Inherits from [class
#     Object](Object.html#class-Object-label-What-27s+Here).
# *   Includes [module
#     Enumerable](Enumerable.html#module-Enumerable-label-What-27s+Here), which
#     provides dozens of additional methods.
#
#
# Here, class Dir provides methods that are useful for:
#
# *   [Reading](#class-Dir-label-Reading)
# *   [Setting](#class-Dir-label-Setting)
# *   [Querying](#class-Dir-label-Querying)
# *   [Iterating](#class-Dir-label-Iterating)
# *   [Other](#class-Dir-label-Other)
#
#
# ### Reading
#
#     #close
# :       Closes the directory stream for `self`.
#
#     #pos=
# :       Sets the position in the directory stream for `self`.
#
#     #read
# :       Reads and returns the next entry in the directory stream for `self`.
#
#     #rewind
# :       Sets the position in the directory stream for `self` to the first
#         entry.
#
#     #seek
# :       Sets the position in the directory stream for `self` the entry at the
#         given offset.
#
#
#
# ### Setting
#
#     ::chdir
# :       Changes the working directory of the current process to the given
#         directory.
#
#     ::chroot
# :       Changes the file-system root for the current process to the given
#         directory.
#
#
#
# ### Querying
#
#     ::[]
# :       Same as ::glob without the ability to pass flags.
#
#     ::children
# :       Returns an array of names of the children (both files and directories)
#         of the given directory, but not including `.` or `..`.
#
#     ::empty?
# :       Returns whether the given path is an empty directory.
#
#     ::entries
# :       Returns an array of names of the children (both files and directories)
#         of the given directory, including `.` and `..`.
#
#     ::exist?
# :       Returns whether the given path is a directory.
#
#     ::getwd (aliased as #pwd)
# :       Returns the path to the current working directory.
#
#     ::glob
# :       Returns an array of file paths matching the given pattern and flags.
#
#     ::home
# :       Returns the home directory path for a given user or the current user.
#
#     #children
# :       Returns an array of names of the children (both files and directories)
#         of `self`, but not including `.` or `..`.
#
#     #fileno
# :       Returns the integer file descriptor for `self`.
#
#     #path (aliased as #to_path)
# :       Returns the path used to create `self`.
#
#     #tell (aliased as #pos)
# :       Returns the integer position in the directory stream for `self`.
#
#
#
# ### Iterating
#
#     ::each_child
# :       Calls the given block with each entry in the given directory, but not
#         including `.` or `..`.
#
#     ::foreach
# :       Calls the given block with each entryin the given directory, including
#         `.` and `..`.
#
#     #each
# :       Calls the given block with each entry in `self`, including `.` and
#         `..`.
#
#     #each_child
# :       Calls the given block with each entry in `self`, but not including `.`
#         or `..`.
#
#
#
# ### Other
#
#     ::mkdir
# :       Creates a directory at the given path, with optional permissions.
#
#     ::new
# :       Returns a new Dir for the given path, with optional encoding.
#
#     ::open
# :       Same as ::new, but if a block is given, yields the Dir to the block,
#         closing it upon block exit.
#
#     ::unlink (aliased as ::delete and ::rmdir)
# :       Removes the given directory.
#
#     #inspect
# :       Returns a string description of `self`.
#
class Dir
  include Enumerable[String]

  # <!--
  #   rdoc-file=dir.rb
  #   - Dir.new( string ) -> aDir
  #   - Dir.new( string, encoding: enc ) -> aDir
  # -->
  # Returns a new directory object for the named directory.
  #
  # The optional *encoding* keyword argument specifies the encoding of the
  # directory. If not specified, the filesystem encoding is used.
  #
  def initialize: (string, ?encoding: encoding | nil) -> void

  # <!--
  #   rdoc-file=dir.rb
  #   - Dir[ string [, string ...] [, base: path] [, sort: true] ] -> array
  # -->
  # Equivalent to calling `Dir.glob([`*string,...*`], 0)`.
  #
  def self.[]: (*string patterns, ?base: string) ?{ (String path) -> void } -> Array[String]

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.chdir( [ string] ) -> 0
  #   - Dir.chdir( [ string] ) {| path | block }  -> anObject
  # -->
  # Changes the current working directory of the process to the given string. When
  # called without an argument, changes the directory to the value of the
  # environment variable `HOME`, or `LOGDIR`. SystemCallError (probably
  # Errno::ENOENT) if the target directory does not exist.
  #
  # If a block is given, it is passed the name of the new current directory, and
  # the block is executed with that as the current directory. The original working
  # directory is restored when the block exits. The return value of `chdir` is the
  # value of the block. `chdir` blocks can be nested, but in a multi-threaded
  # program an error will be raised if a thread attempts to open a `chdir` block
  # while another thread has one open or a call to `chdir` without a block occurs
  # inside a block passed to `chdir` (even in the same thread).
  #
  #     Dir.chdir("/var/spool/mail")
  #     puts Dir.pwd
  #     Dir.chdir("/tmp") do
  #       puts Dir.pwd
  #       Dir.chdir("/usr") do
  #         puts Dir.pwd
  #       end
  #       puts Dir.pwd
  #     end
  #     puts Dir.pwd
  #
  # *produces:*
  #
  #     /var/spool/mail
  #     /tmp
  #     /usr
  #     /tmp
  #     /var/spool/mail
  #
  def self.chdir: (?string) -> void
                | [U] (?string) { (String) -> U } -> U

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.children( dirname )                -> array
  #   - Dir.children( dirname, encoding: enc ) -> array
  # -->
  # Returns an array containing all of the filenames except for "." and ".." in
  # the given directory. Will raise a SystemCallError if the named directory
  # doesn't exist.
  #
  # The optional *encoding* keyword argument specifies the encoding of the
  # directory. If not specified, the filesystem encoding is used.
  #
  #     Dir.children("testdir")   #=> ["config.h", "main.rb"]
  #
  def self.children: (string dirname, ?encoding: string | Encoding | nil enc) -> Array[String]

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.chroot( string ) -> 0
  # -->
  # Changes this process's idea of the file system root. Only a privileged process
  # may make this call. Not available on all platforms. On Unix systems, see
  # `chroot(2)` for more information.
  #
  def self.chroot: (string) -> void

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.delete( string ) -> 0
  #   - Dir.rmdir( string ) -> 0
  #   - Dir.unlink( string ) -> 0
  # -->
  # Deletes the named directory. Raises a subclass of SystemCallError if the
  # directory isn't empty.
  #
  def self.delete: (string) -> void

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.each_child( dirname ) {| filename | block }                 -> nil
  #   - Dir.each_child( dirname, encoding: enc ) {| filename | block }  -> nil
  #   - Dir.each_child( dirname )                                       -> an_enumerator
  #   - Dir.each_child( dirname, encoding: enc )                        -> an_enumerator
  # -->
  # Calls the block once for each entry except for "." and ".." in the named
  # directory, passing the filename of each entry as a parameter to the block.
  #
  # If no block is given, an enumerator is returned instead.
  #
  #     Dir.each_child("testdir") {|x| puts "Got #{x}" }
  #
  # *produces:*
  #
  #     Got config.h
  #     Got main.rb
  #
  def self.each_child: (string dirname, ?encoding: string | Encoding | nil enc) -> Enumerator[String, void]
                     | (string dirname, ?encoding: string | Encoding | nil enc) { (String filename) -> void } -> void

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.empty?(path_name)  ->  true or false
  # -->
  # Returns `true` if the named file is an empty directory, `false` if it is not a
  # directory or non-empty.
  #
  def self.empty?: (string path_name) -> bool

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.entries( dirname )                -> array
  #   - Dir.entries( dirname, encoding: enc ) -> array
  # -->
  # Returns an array containing all of the filenames in the given directory. Will
  # raise a SystemCallError if the named directory doesn't exist.
  #
  # The optional *encoding* keyword argument specifies the encoding of the
  # directory. If not specified, the filesystem encoding is used.
  #
  #     Dir.entries("testdir")   #=> [".", "..", "config.h", "main.rb"]
  #
  def self.entries: (string dirname, ?encoding: encoding | nil enc) -> ::Array[String]

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.exist?(file_name)   ->  true or false
  # -->
  # Returns `true` if the named file is a directory, `false` otherwise.
  #
  def self.exist?: (string file) -> bool

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.foreach( dirname ) {| filename | block }                 -> nil
  #   - Dir.foreach( dirname, encoding: enc ) {| filename | block }  -> nil
  #   - Dir.foreach( dirname )                                       -> an_enumerator
  #   - Dir.foreach( dirname, encoding: enc )                        -> an_enumerator
  # -->
  # Calls the block once for each entry in the named directory, passing the
  # filename of each entry as a parameter to the block.
  #
  # If no block is given, an enumerator is returned instead.
  #
  #     Dir.foreach("testdir") {|x| puts "Got #{x}" }
  #
  # *produces:*
  #
  #     Got .
  #     Got ..
  #     Got config.h
  #     Got main.rb
  #
  alias self.foreach self.each_child

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.getwd -> string
  #   - Dir.pwd -> string
  # -->
  # Returns the path to the current working directory of this process as a string.
  #
  #     Dir.chdir("/tmp")   #=> 0
  #     Dir.getwd           #=> "/tmp"
  #     Dir.pwd             #=> "/tmp"
  #
  def self.getwd: () -> String

  # <!--
  #   rdoc-file=dir.rb
  #   - Dir.glob( pattern, [flags], [base: path] [, sort: true] )                       -> array
  #   - Dir.glob( pattern, [flags], [base: path] [, sort: true] ) { |filename| block }  -> nil
  # -->
  # Expands `pattern`, which is a pattern string or an Array of pattern strings,
  # and returns an array containing the matching filenames. If a block is given,
  # calls the block once for each matching filename, passing the filename as a
  # parameter to the block.
  #
  # The optional `base` keyword argument specifies the base directory for
  # interpreting relative pathnames instead of the current working directory. As
  # the results are not prefixed with the base directory name in this case, you
  # will need to prepend the base directory name if you want real paths.
  #
  # The results which matched single wildcard or character set are sorted in
  # binary ascending order, unless `false` is given as the optional `sort` keyword
  # argument.  The order of an Array of pattern strings and braces are preserved.
  #
  # Note that the pattern is not a regexp, it's closer to a shell glob. See
  # File::fnmatch for the meaning of the `flags` parameter. Case sensitivity
  # depends on your system (`File::FNM_CASEFOLD` is ignored).
  #
  # `*`
  # :   Matches any file. Can be restricted by other values in the glob.
  #     Equivalent to `/.*/mx` in regexp.
  #
  #     `*`
  # :       Matches all files
  #     `c*`
  # :       Matches all files beginning with `c`
  #     `*c`
  # :       Matches all files ending with `c`
  #     `*c*`
  # :       Match all files that have `c` in them (including at the beginning or
  #         end).
  #
  #
  #     Note, this will not match Unix-like hidden files (dotfiles).  In order to
  #     include those in the match results, you must use the File::FNM_DOTMATCH
  #     flag or something like `"{*,.*}"`.
  #
  # `**`
  # :   Matches directories recursively if followed by `/`.  If this path segment
  #     contains any other characters, it is the same as the usual `*`.
  #
  # `?`
  # :   Matches any one character. Equivalent to `/.{1}/` in regexp.
  #
  # `[set]`
  # :   Matches any one character in `set`.  Behaves exactly like character sets
  #     in Regexp, including set negation (`[^a-z]`).
  #
  # `{p,q}`
  # :   Matches either literal `p` or literal `q`. Equivalent to pattern
  #     alternation in regexp.
  #
  #     Matching literals may be more than one character in length.  More than two
  #     literals may be specified.
  #
  # `\`
  # :   Escapes the next metacharacter.
  #
  #     Note that this means you cannot use backslash on windows as part of a
  #     glob, i.e.  `Dir["c:\\foo*"]` will not work, use `Dir["c:/foo*"]` instead.
  #
  #
  # Examples:
  #
  #     Dir["config.?"]                     #=> ["config.h"]
  #     Dir.glob("config.?")                #=> ["config.h"]
  #     Dir.glob("*.[a-z][a-z]")            #=> ["main.rb"]
  #     Dir.glob("*.[^r]*")                 #=> ["config.h"]
  #     Dir.glob("*.{rb,h}")                #=> ["main.rb", "config.h"]
  #     Dir.glob("*")                       #=> ["config.h", "main.rb"]
  #     Dir.glob("*", File::FNM_DOTMATCH)   #=> [".", "config.h", "main.rb"]
  #     Dir.glob(["*.rb", "*.h"])           #=> ["main.rb", "config.h"]
  #
  #     Dir.glob("**/*.rb")                 #=> ["main.rb",
  #                                         #    "lib/song.rb",
  #                                         #    "lib/song/karaoke.rb"]
  #
  #     Dir.glob("**/*.rb", base: "lib")    #=> ["song.rb",
  #                                         #    "song/karaoke.rb"]
  #
  #     Dir.glob("**/lib")                  #=> ["lib"]
  #
  #     Dir.glob("**/lib/**/*.rb")          #=> ["lib/song.rb",
  #                                         #    "lib/song/karaoke.rb"]
  #
  #     Dir.glob("**/lib/*.rb")             #=> ["lib/song.rb"]
  #
  def self.glob: (string | ::Array[string] pattern, ?Integer flags, ?base: string) -> ::Array[String]
               | (string | ::Array[string] pattern, ?Integer flags, ?base: string) { (String) -> void } -> void

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.home()       -> "/home/me"
  #   - Dir.home("root") -> "/root"
  # -->
  # Returns the home directory of the current user or the named user if given.
  #
  def self.home: (?string user) -> String

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.mkdir( string [, integer] ) -> 0
  # -->
  # Makes a new directory named by *string*, with permissions specified by the
  # optional parameter *anInteger*. The permissions may be modified by the value
  # of File::umask, and are ignored on NT. Raises a SystemCallError if the
  # directory cannot be created. See also the discussion of permissions in the
  # class documentation for File.
  #
  #     Dir.mkdir(File.join(Dir.home, ".foo"), 0700) #=> 0
  #
  def self.mkdir: (string, ?Integer permissions) -> void

  # <!--
  #   rdoc-file=dir.rb
  #   - Dir.open( string ) -> aDir
  #   - Dir.open( string, encoding: enc ) -> aDir
  #   - Dir.open( string ) {| aDir | block } -> anObject
  #   - Dir.open( string, encoding: enc ) {| aDir | block } -> anObject
  # -->
  # The optional *encoding* keyword argument specifies the encoding of the
  # directory. If not specified, the filesystem encoding is used.
  #
  # With no block, `open` is a synonym for Dir::new. If a block is present, it is
  # passed *aDir* as a parameter. The directory is closed at the end of the block,
  # and Dir::open returns the value of the block.
  #
  def self.open: (string, ?encoding: encoding | nil) -> Dir
               | [U] (string, ?encoding: encoding | nil) { (Dir) -> U } -> U

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.getwd -> string
  #   - Dir.pwd -> string
  # -->
  # Returns the path to the current working directory of this process as a string.
  #
  #     Dir.chdir("/tmp")   #=> 0
  #     Dir.getwd           #=> "/tmp"
  #     Dir.pwd             #=> "/tmp"
  #
  def self.pwd: () -> String

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.delete( string ) -> 0
  #   - Dir.rmdir( string ) -> 0
  #   - Dir.unlink( string ) -> 0
  # -->
  # Deletes the named directory. Raises a subclass of SystemCallError if the
  # directory isn't empty.
  #
  alias self.rmdir self.delete

  # <!--
  #   rdoc-file=dir.c
  #   - Dir.delete( string ) -> 0
  #   - Dir.rmdir( string ) -> 0
  #   - Dir.unlink( string ) -> 0
  # -->
  # Deletes the named directory. Raises a subclass of SystemCallError if the
  # directory isn't empty.
  #
  alias self.unlink self.delete

  public

  # <!--
  #   rdoc-file=dir.c
  #   - dir.children  -> array
  # -->
  # Returns an array containing all of the filenames except for "." and ".." in
  # this directory.
  #
  #     d = Dir.new("testdir")
  #     d.children   #=> ["config.h", "main.rb"]
  #
  def children: () -> Array[String]

  # <!--
  #   rdoc-file=dir.c
  #   - dir.close -> nil
  # -->
  # Closes the directory stream. Calling this method on closed Dir object is
  # ignored since Ruby 2.3.
  #
  #     d = Dir.new("testdir")
  #     d.close   #=> nil
  #
  def close: () -> void

  # <!--
  #   rdoc-file=dir.c
  #   - dir.each { |filename| block }  -> dir
  #   - dir.each                       -> an_enumerator
  # -->
  # Calls the block once for each entry in this directory, passing the filename of
  # each entry as a parameter to the block.
  #
  # If no block is given, an enumerator is returned instead.
  #
  #     d = Dir.new("testdir")
  #     d.each  {|x| puts "Got #{x}" }
  #
  # *produces:*
  #
  #     Got .
  #     Got ..
  #     Got config.h
  #     Got main.rb
  #
  def each: () { (String) -> void } -> self
          | () -> ::Enumerator[String, self]

  # <!--
  #   rdoc-file=dir.c
  #   - dir.each_child {| filename | block }  -> dir
  #   - dir.each_child                        -> an_enumerator
  # -->
  # Calls the block once for each entry except for "." and ".." in this directory,
  # passing the filename of each entry as a parameter to the block.
  #
  # If no block is given, an enumerator is returned instead.
  #
  #     d = Dir.new("testdir")
  #     d.each_child  {|x| puts "Got #{x}" }
  #
  # *produces:*
  #
  #     Got config.h
  #     Got main.rb
  #
  def each_child: () { (String) -> void } -> self
                | () -> ::Enumerator[String, self]

  # <!--
  #   rdoc-file=dir.c
  #   - dir.fileno -> integer
  # -->
  # Returns the file descriptor used in *dir*.
  #
  #     d = Dir.new("..")
  #     d.fileno   #=> 8
  #
  # This method uses dirfd() function defined by POSIX 2008. NotImplementedError
  # is raised on other platforms, such as Windows, which doesn't provide the
  # function.
  #
  def fileno: () -> Integer

  # <!--
  #   rdoc-file=dir.c
  #   - dir.inspect -> string
  # -->
  # Return a string describing this Dir object.
  #
  def inspect: () -> String

  # <!--
  #   rdoc-file=dir.c
  #   - dir.path -> string or nil
  #   - dir.to_path -> string or nil
  # -->
  # Returns the path parameter passed to *dir*'s constructor.
  #
  #     d = Dir.new("..")
  #     d.path   #=> ".."
  #
  def path: () -> String?

  # <!-- rdoc-file=dir.c -->
  # Returns the current position in *dir*. See also Dir#seek.
  #
  #     d = Dir.new("testdir")
  #     d.tell   #=> 0
  #     d.read   #=> "."
  #     d.tell   #=> 12
  #
  def pos: () -> Integer

  # <!--
  #   rdoc-file=dir.c
  #   - dir.pos = integer  -> integer
  # -->
  # Synonym for Dir#seek, but returns the position parameter.
  #
  #     d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
  #     d.read                   #=> "."
  #     i = d.pos                #=> 12
  #     d.read                   #=> ".."
  #     d.pos = i                #=> 12
  #     d.read                   #=> ".."
  #
  def pos=: (Integer pos) -> Integer

  # <!--
  #   rdoc-file=dir.c
  #   - dir.read -> string or nil
  # -->
  # Reads the next entry from *dir* and returns it as a string. Returns `nil` at
  # the end of the stream.
  #
  #     d = Dir.new("testdir")
  #     d.read   #=> "."
  #     d.read   #=> ".."
  #     d.read   #=> "config.h"
  #
  def read: () -> String?

  # <!--
  #   rdoc-file=dir.c
  #   - dir.rewind -> dir
  # -->
  # Repositions *dir* to the first entry.
  #
  #     d = Dir.new("testdir")
  #     d.read     #=> "."
  #     d.rewind   #=> #<Dir:0x401b3fb0>
  #     d.read     #=> "."
  #
  def rewind: () -> self

  # <!--
  #   rdoc-file=dir.c
  #   - dir.seek( integer ) -> dir
  # -->
  # Seeks to a particular location in *dir*. *integer* must be a value returned by
  # Dir#tell.
  #
  #     d = Dir.new("testdir")   #=> #<Dir:0x401b3c40>
  #     d.read                   #=> "."
  #     i = d.tell               #=> 12
  #     d.read                   #=> ".."
  #     d.seek(i)                #=> #<Dir:0x401b3c40>
  #     d.read                   #=> ".."
  #
  def seek: (Integer) -> self

  # <!--
  #   rdoc-file=dir.c
  #   - dir.pos -> integer
  #   - dir.tell -> integer
  # -->
  # Returns the current position in *dir*. See also Dir#seek.
  #
  #     d = Dir.new("testdir")
  #     d.tell   #=> 0
  #     d.read   #=> "."
  #     d.tell   #=> 12
  #
  def tell: () -> Integer

  # <!-- rdoc-file=dir.c -->
  # Returns the path parameter passed to *dir*'s constructor.
  #
  #     d = Dir.new("..")
  #     d.path   #=> ".."
  #
  alias to_path path
end
