Next: , Previous: digraph, Up: Top


21 dir

     %--------------------------------------------------%
     % vim: ft=mercury ts=4 sw=4 et
     %--------------------------------------------------%
     % Copyright (C) 1994-1995,1997,1999-2000,2002-2012 The University of Melbourne.
     % This file may only be copied under the terms of the GNU Library General
     % Public License - see the file COPYING.LIB in the Mercury distribution.
     %--------------------------------------------------%
     %
     % File: dir.m.
     % Main authors: fjh, stayl.
     % Stability: high.
     %
     % Filename and directory handling.
     %
     % Note that the predicates and functions in this module change directory
     % separators in paths passed to them to the normal separator for the platform,
     % if that doesn't change the meaning of the path name.
     %
     % Duplicate directory separators and trailing separators are also removed
     % where that doesn't change the meaning of the path name.
     %
     %--------------------------------------------------%
     %--------------------------------------------------%
     
     :- module dir.
     :- interface.
     
     :- import_module bool.
     :- import_module io.
     :- import_module list.
     
     %--------------------------------------------------%
     %
     % Predicates to isolate system dependencies
     %
     
         % Returns the default separator between components of a pathname --
         % '/' on Unix systems and '\\' on Microsoft Windows systems.
         %
     :- func dir.directory_separator = character.
     :- pred dir.directory_separator(character::out) is det.
     
         % Is the character a directory separator.
         % On Microsoft Windows systems this will succeed for '/'
         % as well as '\\'.
         %
     :- pred dir.is_directory_separator(character).
     :- mode dir.is_directory_separator(in) is semidet.
     :- mode dir.is_directory_separator(out) is multi.
     
         % Returns ".".
         %
     :- func dir.this_directory = string.
     :- pred dir.this_directory(string::out) is det.
     
         % Returns "..".
         %
     :- func dir.parent_directory = string.
     :- pred dir.parent_directory(string::out) is det.
     
         % dir.split_name(PathName, DirName, BaseName).
         %
         % Split a filename into a directory part and a filename part.
         %
         % Fails for root directories or relative filenames not containing
         % directory information.
         %
         % Trailing slashes are removed from PathName before splitting,
         % if that doesn't change the meaning of PathName.
         %
         % Trailing slashes are removed from DirName after splitting,
         % if that doesn't change the meaning of DirName.
         %
         % On Windows, drive current directories are handled correctly,
         % for example `dir.split_name("C:foo", "C:", "foo")'.
         % (`X:' is the current directory on drive `X').
         % Note that Cygwin doesn't support drive current directories,
         % so `dir.split_name("C:foo, _, _)' will fail when running under Cygwin.
         %
     :- pred dir.split_name(string::in, string::out, string::out) is semidet.
     
         % dir.basename(PathName) = BaseName.
         %
         % Returns the non-directory part of a filename.
         %
         % Fails when given a root directory, ".", ".." or a Windows path
         % such as "X:".
         %
         % Trailing slashes are removed from PathName before splitting,
         % if that doesn't change the meaning of PathName.
         %
     :- func dir.basename(string) = string is semidet.
     :- pred dir.basename(string::in, string::out) is semidet.
     
         % As above, but throws an exception instead of failing.
         %
     :- func dir.det_basename(string) = string.
     
         % dir.dirname(PathName) = DirName.
         %
         % Returns the directory part of a filename.
         %
         % Returns PathName if it specifies a root directory.
         %
         % Returns PathName for Windows paths such as "X:".
         %
         % Returns `dir.this_directory' when given a filename
         % without any directory information (e.g. "foo").
         %
         % Trailing slashes in PathName are removed first, if that doesn't change
         % the meaning of PathName.
         %
         % Trailing slashes are removed from DirName after splitting,
         % if that doesn't change the meaning of DirName.
         %
     :- func dir.dirname(string) = string.
     :- pred dir.dirname(string::in, string::out) is det.
     
         % dir.path_name_is_absolute(PathName)
         %
         % Is the path name syntactically an absolute path
         % (this doesn't check whether the path exists).
         %
         % An path is absolute iff it begins with a root directory
         % (see dir.path_name_is_root_directory).
         %
     :- pred dir.path_name_is_absolute(string::in) is semidet.
     
         % dir.path_name_is_root_directory(PathName)
         %
         % On Unix, '/' is the only root directory.
         % On Windows, a root directory is one of the following:
         %   'X:\', which specifies the root directory of drive X,
         %       where X is any letter.
         %   '\', which specifies the root directory of the current drive.
         %   '\\server\share\', which specifies a UNC (Universal Naming
         %       Convention) root directory for a network drive.
         %
         % Note that 'X:' is not a Windows root directory -- it specifies the
         % current directory on drive X, where X is any letter.
         %
     :- pred dir.path_name_is_root_directory(string::in) is semidet.
     
         % PathName = DirName / FileName
         %
         % Given a directory name and a filename, return the pathname of that
         % file in that directory.
         %
         % Duplicate directory separators will not be introduced if
         % DirName ends with a directory separator.
         %
         % On Windows, a call such as `"C:"/"foo"' will return "C:foo".
         %
         % Throws an exception if FileName is an absolute path name.
         % Throws an exception on Windows if FileName is a current
         % drive relative path such as "C:".
         %
     :- func string / string = string.
     :- func dir.make_path_name(string, string) = string.
     
         % relative_path_name_from_components(List) = PathName.
         %
         % Return the relative pathname from the components in the list.  The
         % components of the list must not contain directory separators.
         %
     :- func dir.relative_path_name_from_components(list(string)) = string.
     
     %--------------------------------------------------%
     
         % dir.current_directory(Result)
         % Return the current working directory.
         %
     :- pred dir.current_directory(io.res(string)::out, io::di, io::uo) is det.
     
     %--------------------------------------------------%
     
         % Make the given directory, and all parent directories.
         % This will also succeed if the directory already exists
         % and is readable and writable by the current user.
         %
     :- pred dir.make_directory(string::in, io.res::out, io::di, io::uo) is det.
     
         % Make only the given directory.
         % Fails if the directory already exists, or the parent directory doesn't.
         %
     :- pred dir.make_single_directory(string::in, io.res::out, io::di, io::uo)
         is det.
     
     %--------------------------------------------------%
     
         % FoldlPred(DirName, BaseName, FileType, Continue, !Data, !IO).
         %
         % A predicate passed to dir.foldl2 to process each entry in a directory.
         % Processing will stop if Continue is bound to `no'.
         %
     :- type dir.foldl_pred(T) ==
         pred(string, string, io.file_type, bool, T, T, io, io).
     :- inst dir.foldl_pred == (pred(in, in, in, out, in, out, di, uo) is det).
     
         % dir.foldl2(P, DirName, InitialData, Result, !IO).
         %
         % Apply `P' to all files and directories in the given directory.
         % Directories are not processed recursively.
         % Processing will stop if the boolean (Continue) output of P is bound
         % to `no'.
         % The order in which the entries are processed is unspecified.
         %
     :- pred dir.foldl2(dir.foldl_pred(T)::in(dir.foldl_pred), string::in,
         T::in, io.maybe_partial_res(T)::out, io::di, io::uo) is det.
     
         % dir.recursive_foldl2(P, DirName, FollowSymLinks,
         %   InitialData, Result, !IO).
         %
         % As above, but recursively process subdirectories.
         % Subdirectories are processed depth-first, processing the directory itself
         % before its contents. If `FollowSymLinks' is `yes', recursively process
         % the directories referenced by symbolic links.
         %
     :- pred dir.recursive_foldl2(dir.foldl_pred(T)::in(dir.foldl_pred),
         string::in, bool::in, T::in, io.maybe_partial_res(T)::out,
         io::di, io::uo) is det.
     
     %--------------------------------------------------%
     
         % Implement brace expansion, as in sh: return the sequence of strings
         % generated from the given input string. Throw an exception if the
         % input string contains mismatched braces.
         %
         % The following is the documentation of brace expansion from the sh manual:
         %
         %   Brace expansion is a mechanism by which arbitrary strings may be
         %   generated. This mechanism is similar to pathname expansion, but the
         %   filenames generated need not exist. Patterns to be brace expanded
         %   take the form of an optional preamble, followed by a series of
         %   comma-separated strings between a pair of braces, followed by an
         %   optional postscript. The preamble is prefixed to each string contained
         %   within the braces, and the postscript is then appended to each
         %   resulting string, expanding left to right.
         %
         %   Brace expansions may be nested. The results of each expanded string
         %   are not sorted; left to right order is preserved. For example,
         %   a{d,c,b}e expands into `ade ace abe'.
         %
     :- func expand_braces(string) = list(string).
     
     %--------------------------------------------------%
     %--------------------------------------------------%