=encoding utf8

=head1 NAME

Sidef::Types::Glob::Dir - Directory manipulation and navigation in Sidef

=head1 DESCRIPTION

The Dir class provides comprehensive directory manipulation capabilities in Sidef, including creation, deletion, navigation, and traversal of directory structures. It inherits from the File class, providing access to all file-related methods while adding directory-specific functionality.

This class handles both simple directory operations (like creating or removing single directories) and complex operations (like recursive directory traversal and tree manipulation). All directory paths are properly encoded/decoded to handle Unicode filenames correctly.

=head1 SYNOPSIS

    # Create a Dir object
    var dir = Dir("/path/to/directory")
    var home = Dir.home
    var temp = Dir.tmp
    
    # Directory creation
    dir.make                    # Create single directory
    dir.mkpath                  # Create directory with parents
    
    # Directory navigation
    Dir.cwd                     # Get current working directory
    dir.chdir                   # Change to this directory
    dir.parent                  # Get parent directory
    dir.up                      # Go up one level
    
    # Directory operations
    dir.is_empty                # Check if directory is empty
    dir.delete                  # Remove empty directory
    dir.remove_tree             # Recursively remove directory and contents
    
    # Directory traversal
    dir.find { |file|
        say file                # Iterate over all files and subdirectories
    }
    
    # Path manipulation
    var subdir = dir + "subdir" # Concatenate paths
    var parts = dir.split       # Split path into components

=head1 INHERITS

Inherits methods from:

       * Sidef::Types::Glob::File

=head1 METHODS

=head2 new

    Dir.new(path)
    Dir(path)
    Dir(part1, part2, ...)

Creates a new Dir object. Can accept a single path string or multiple path components that will be joined using the platform-specific directory separator.

    var dir1 = Dir("/home/user")
    var dir2 = Dir("home", "user", "documents")
    var dir3 = Dir(file_obj)  # Convert File object to Dir

Returns a new Dir object representing the specified path.

Aliases: I<call>

=head2 +

    dir + name

Concatenates a filename or directory name to the current directory path, returning an appropriate object (File if the name looks like a file, Dir if it's a directory).

    var home = Dir.home
    var docs = home + "Documents"      # Returns Dir object
    var file = home + "file.txt"       # Returns File object

Returns a File or Dir object with the concatenated path.

Aliases: I<concat>, I<catfile>

=head2 chdir

    dir.chdir

Changes the current working directory to this directory's path. This affects the process-wide current directory.

    var dir = Dir("/tmp")
    dir.chdir                          # Current directory is now /tmp
    
Returns true if successful, false otherwise.

=head2 chroot

    dir.chroot

Changes the root directory to this directory. This is a restricted operation typically requiring superuser privileges and affects the entire process.

    var dir = Dir("/jail")
    dir.chroot                         # Root is now /jail

Returns true if successful, false otherwise.

=head2 cwd

    Dir.cwd

Returns a Dir object representing the current working directory (absolute path).

    var current = Dir.cwd
    say current                        # Prints current directory path

This is a class method that can be called on Dir itself.

=head2 delete

    dir.delete

Removes the directory. The directory must be empty for this operation to succeed. For non-empty directories, use C<remove_tree> instead.

    var dir = Dir("empty_dir")
    dir.delete                         # Removes the empty directory

Returns true if successful, false otherwise.

Aliases: I<remove>, I<unlink>

=head2 dump

    dir.dump

Returns a string representation of the Dir object suitable for debugging, showing it as a Dir constructor call.

    var dir = Dir("/tmp")
    say dir.dump                       # Prints: Dir("/tmp")

Returns a String object containing the dump representation.

=head2 find

    dir.find(block)
    dir.find

Recursively traverses the directory tree. When given a block, calls the block for each file and subdirectory found. When called without arguments, returns an array of all files and subdirectories.

    # Using a block
    dir.find { |item|
        say item if item.is_file
    }
    
    # Getting an array
    var all_items = dir.find
    say "Found #{all_items.len} items"

The block receives File objects for files and Dir objects for directories.

Returns the Dir object itself when used with a block, or an Array of all items when used without arguments.

Aliases: I<browse>

=head2 home

    Dir.home

Returns a Dir object representing the user's home directory. This method attempts to determine the home directory through various means: the HOME or LOGDIR environment variables, system user database lookup, or the File::HomeDir module.

    var home = Dir.home
    say home                           # e.g., /home/username

This is a class method.

=head2 is_empty

    dir.is_empty

Checks whether the directory is empty (contains no files or subdirectories, excluding "." and "..").

    var dir = Dir("test")
    if (dir.is_empty) {
        say "Directory is empty"
    }

Returns true if empty, false if not empty, or nil if the directory cannot be opened.

=head2 make

    dir.make

Creates the directory. The parent directory must already exist. For creating directories with parent paths, use C<mkpath> instead.

    var dir = Dir("newdir")
    dir.make                           # Creates newdir in current directory

Returns true if successful, false otherwise.

Aliases: I<mkdir>, I<create>

=head2 mkpath

    dir.mkpath

Creates the directory along with any necessary parent directories (similar to C<mkdir -p>). If the directory already exists, returns true.

    var dir = Dir("/path/to/deep/nested/dir")
    dir.mkpath                         # Creates all intermediate directories

Returns true if successful or already exists, false otherwise.

Aliases: I<mktree>, I<make_path>, I<make_tree>, I<create_tree>

=head2 mktemp

    Dir.mktemp(opts)

Creates a temporary directory with a unique name. The directory will be automatically cleaned up when the program exits. Options can be passed as named parameters to customize the temporary directory creation.

    var tmpdir = Dir.mktemp
    say tmpdir                         # e.g., /tmp/XXXXXXXXXX
    
    var custom = Dir.mktemp(TEMPLATE => "myapp_XXXX")

Returns a Dir object representing the temporary directory.

Aliases: I<make_tmp>, I<make_temp>

=head2 open

    dir.open
    dir.open(fh_ref)
    dir.open(fh_ref, err_ref)

Opens the directory for reading, returning a DirHandle object. Can optionally store the handle in a reference variable and capture any error message.

    # Simple usage
    var dh = dir.open
    
    # With references
    var fh_ref = \nil
    var err_ref = \nil
    if (dir.open(fh_ref, err_ref)) {
        # Success - use *fh_ref
    } else {
        say "Error: #{*err_ref}"
    }

Returns a DirHandle object on success, or nil on failure. When called with references, returns true/false and stores the handle/error in the references.

Aliases: I<open_r>

=head2 open_rw

    dir.open_rw

Reserved for future implementation. Currently not operational.

=head2 open_w

    dir.open_w

Reserved for future implementation. Currently not operational.

=head2 parent

    dir.parent

Returns a Dir object representing the parent directory of the current directory.

    var dir = Dir("/home/user/documents")
    var parent = dir.parent            # Dir("/home/user")

Returns a Dir object.

=head2 pwd

    Dir.pwd

Returns a Dir object representing the current directory as ".". Unlike C<cwd>, this returns a relative path representation.

    var here = Dir.pwd                 # Dir(".")

This is a class method.

=head2 remove_tree

    dir.remove_tree

Recursively removes the directory and all its contents (files and subdirectories). Use with caution as this operation cannot be undone.

    var dir = Dir("old_project")
    dir.remove_tree                    # Removes directory and everything in it

Returns true if successful, false otherwise.

=head2 root

    Dir.root

Returns a Dir object representing the root directory of the filesystem ("/" on Unix-like systems, or the appropriate root on other platforms).

    var root = Dir.root
    say root                           # Prints: /

This is a class method.

=head2 split

    dir.split

Splits the directory path into its component parts, returning an array of strings.

    var dir = Dir("/home/user/documents")
    var parts = dir.split              # ["", "home", "user", "documents"]
    
    var rel = Dir("path/to/dir")
    var components = rel.split         # ["path", "to", "dir"]

Returns an Array of String objects representing each path component.

=head2 tmp

    Dir.tmp

Returns a Dir object representing the system's temporary directory.

    var tmpdir = Dir.tmp
    say tmpdir                         # e.g., /tmp on Unix, C:\Temp on Windows

This is a class method.

Aliases: I<temp>

=head2 to_dir

    dir.to_dir

Returns the Dir object itself. Useful for ensuring an object is a Dir type.

    var dir = some_object.to_dir

Returns the Dir object.

=head2 to_s

    dir.to_s

Converts the Dir object to a String containing the directory path.

    var dir = Dir("/home/user")
    var path = dir.to_s                # String: "/home/user"
    say path                           # Prints: /home/user

Returns a String object.

Aliases: I<to_str>

=head2 up

    dir.up

Returns a Dir object representing one level up from the current directory (equivalent to appending "..").

    var dir = Dir("/home/user/documents")
    var parent = dir.up                # Dir("/home/user/documents/..")
    
    var updir = Dir.up                 # Dir("..")

Can be called as both instance and class method.

=head1 EXAMPLES

=head2 Basic Directory Operations

    # Create and navigate directories
    var project = Dir("my_project")
    project.mkpath
    project.chdir
    
    # Create subdirectories
    var src = project + "src"
    var lib = project + "lib"
    src.make
    lib.make

=head2 Directory Traversal

    # Find all .txt files recursively
    var docs = Dir("documents")
    docs.find { |item|
        if (item.is_file && item.match(/\.txt$/)) {
            say item
        }
    }
    
    # Get list of all items
    var all = docs.find
    say "Total items: #{all.len}"

=head2 Working with Temporary Directories

    # Create temporary directory for processing
    var tmpdir = Dir.mktemp
    say "Using temp directory: #{tmpdir}"
    
    # Do work in temp directory
    tmpdir.chdir
    # ... operations ...
    
    # Temp directory automatically cleaned up on exit

=head2 Directory Cleanup

    # Remove empty directory
    var old = Dir("obsolete")
    if (old.is_empty) {
        old.delete
    }
    
    # Remove directory tree
    var cache = Dir(".cache")
    cache.remove_tree  # Removes everything recursively

=head1 SEE ALSO

L<Sidef::Types::Glob::File>, L<Sidef::Types::Glob::DirHandle>

=head1 AUTHOR

Daniel Șuteu

=cut
