Compatible Doclog docs for library(files)
This commit is contained in:
147
src/lib/files.pl
147
src/lib/files.pl
@@ -1,3 +1,22 @@
|
|||||||
|
/** Predicates for reasoning about files and directories.
|
||||||
|
|
||||||
|
In this library, directories and files are represented as
|
||||||
|
*lists of characters*. This is an ideal representation:
|
||||||
|
|
||||||
|
* Lists of characters can be conveniently reasoned about with DCGs
|
||||||
|
and built-in Prolog predicates from library(lists). This alone
|
||||||
|
is already a very compelling argument to use them.
|
||||||
|
* Other Scryer libraries such as library(http/http_open) also already
|
||||||
|
use lists of characters to represent paths.
|
||||||
|
* File names are mostly ephemeral, so it is good for efficiency
|
||||||
|
that they can quickly allocated transiently on the heap, leaving the
|
||||||
|
atom table mostly unaffected. Indexing is almost never needed
|
||||||
|
for file names. If needed, it should be added to the engine.
|
||||||
|
* The previous point is also good for security, since the system
|
||||||
|
leaves little trace of which files were even accessed.
|
||||||
|
* Scryer Prolog represents lists of characters extremely compactly.
|
||||||
|
*/
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
||||||
Written 2020, 2022 by Markus Triska (triska@metalevel.at)
|
Written 2020, 2022 by Markus Triska (triska@metalevel.at)
|
||||||
Part of Scryer Prolog.
|
Part of Scryer Prolog.
|
||||||
@@ -67,41 +86,74 @@
|
|||||||
:- use_module(library(charsio)).
|
:- use_module(library(charsio)).
|
||||||
:- use_module(library(dcgs)).
|
:- use_module(library(dcgs)).
|
||||||
|
|
||||||
|
%% directory_files(+Directory, -Files).
|
||||||
|
%
|
||||||
|
% Returns the list of files *and* directories available at a specific
|
||||||
|
% directory in the current system.
|
||||||
|
|
||||||
directory_files(Directory, Files) :-
|
directory_files(Directory, Files) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
can_be(list, Files),
|
can_be(list, Files),
|
||||||
'$directory_files'(Directory, Files).
|
'$directory_files'(Directory, Files).
|
||||||
|
|
||||||
|
%% file_size(+File, -Size).
|
||||||
|
%
|
||||||
|
% Returns the size (in bytes) of a file. The file must exist.
|
||||||
|
|
||||||
file_size(File, Size) :-
|
file_size(File, Size) :-
|
||||||
file_must_exist(File, file_size/2),
|
file_must_exist(File, file_size/2),
|
||||||
can_be(integer, Size),
|
can_be(integer, Size),
|
||||||
'$file_size'(File, Size).
|
'$file_size'(File, Size).
|
||||||
|
|
||||||
|
%% file_exists(+File).
|
||||||
|
%
|
||||||
|
% Succeeds if File is a file that exists in the current system.
|
||||||
file_exists(File) :-
|
file_exists(File) :-
|
||||||
must_be(chars, File),
|
must_be(chars, File),
|
||||||
'$file_exists'(File).
|
'$file_exists'(File).
|
||||||
|
|
||||||
|
%% directory_exists(+Directory).
|
||||||
|
%
|
||||||
|
% Succeeds if Directory is a directory that exists in the current system.
|
||||||
directory_exists(Directory) :-
|
directory_exists(Directory) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
'$directory_exists'(Directory).
|
'$directory_exists'(Directory).
|
||||||
|
|
||||||
|
%% make_directory(+Directory).
|
||||||
|
%
|
||||||
|
% Succeeds if it creates a new directory named Directory in the current system.
|
||||||
|
% If you want to create a nested directory, use make\_directory\_path/1.
|
||||||
make_directory(Directory) :-
|
make_directory(Directory) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
'$make_directory'(Directory).
|
'$make_directory'(Directory).
|
||||||
|
|
||||||
|
%% make_directory_path(+Directory).
|
||||||
|
%
|
||||||
|
% Similar to make\_directory/1 but recursively creates directories if they're missing.
|
||||||
|
% Equivalent to mkdir -p in Unix.
|
||||||
make_directory_path(Directory) :-
|
make_directory_path(Directory) :-
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
'$make_directory_path'(Directory).
|
'$make_directory_path'(Directory).
|
||||||
|
|
||||||
|
%% delete_file(+File).
|
||||||
|
%
|
||||||
|
% Succeeds if deletes File from the current system.
|
||||||
delete_file(File) :-
|
delete_file(File) :-
|
||||||
file_must_exist(File, delete_file/1),
|
file_must_exist(File, delete_file/1),
|
||||||
'$delete_file'(File).
|
'$delete_file'(File).
|
||||||
|
|
||||||
|
%% rename_file(+File, +Renamed).
|
||||||
|
%
|
||||||
|
% Succeeds if File is renamed to Renamed
|
||||||
rename_file(File, Renamed) :-
|
rename_file(File, Renamed) :-
|
||||||
file_must_exist(File, rename_file/2),
|
file_must_exist(File, rename_file/2),
|
||||||
must_be(chars, Renamed),
|
must_be(chars, Renamed),
|
||||||
'$rename_file'(File, Renamed).
|
'$rename_file'(File, Renamed).
|
||||||
|
|
||||||
|
%% delete_directory(+Directory).
|
||||||
|
%
|
||||||
|
% Succeeds if Directory is deleted from the current system.
|
||||||
|
% Directory must be empty.
|
||||||
delete_directory(Directory) :-
|
delete_directory(Directory) :-
|
||||||
directory_must_exist(Directory, delete_directory/1),
|
directory_must_exist(Directory, delete_directory/1),
|
||||||
must_be(chars, Directory),
|
must_be(chars, Directory),
|
||||||
@@ -117,31 +169,31 @@ directory_must_exist(Directory, Context) :-
|
|||||||
; throw(error(existence_error(directory, Directory), Context))
|
; throw(error(existence_error(directory, Directory), Context))
|
||||||
).
|
).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% workind_directory(Dir0, Dir).
|
||||||
Dir0 is the current working directory, and the working directory
|
%
|
||||||
is changed to Dir.
|
% Dir0 is the current working directory, and the working directory
|
||||||
|
% is changed to Dir.
|
||||||
|
|
||||||
Use working_directory(Ds, Ds) to determine the current working directory,
|
% Use `working\_directory(Ds, Ds)` to determine the current working directory,
|
||||||
and leave it as is.
|
% and leave it as is.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
working_directory(Dir0, Dir) :-
|
working_directory(Dir0, Dir) :-
|
||||||
can_be(list, Dir0),
|
can_be(list, Dir0),
|
||||||
can_be(list, Dir),
|
can_be(list, Dir),
|
||||||
'$working_directory'(Dir0, Dir).
|
'$working_directory'(Dir0, Dir).
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% path_canonical(Ps, Cs).
|
||||||
True iff Cs is the canonical, absolute path of Ps.
|
%
|
||||||
|
% True iff Cs is the canonical, absolute path of Ps.
|
||||||
All intermediate components are normalized, and all symbolic links
|
%
|
||||||
are resolved.
|
% All intermediate components are normalized, and all symbolic links
|
||||||
|
% are resolved.
|
||||||
The predicate fails in the following situations, though not
|
%
|
||||||
necessarily *only* in these cases:
|
% The predicate fails in the following situations, though not
|
||||||
|
% necessarily *only* in these cases:
|
||||||
1. Ps is a path that does not exist.
|
%
|
||||||
2. A non-final component in Ps is not a directory.
|
% 1. Ps is a path that does not exist.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
% 2. A non-final component in Ps is not a directory.
|
||||||
|
|
||||||
path_canonical(Ps, Cs) :-
|
path_canonical(Ps, Cs) :-
|
||||||
must_be(chars, Ps),
|
must_be(chars, Ps),
|
||||||
@@ -155,12 +207,27 @@ path_canonical(Ps, Cs) :-
|
|||||||
For two time stamps A and B, if A precedes B, then A @< B holds.
|
For two time stamps A and B, if A precedes B, then A @< B holds.
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
||||||
|
|
||||||
|
%% file_modification_time(+File, -T).
|
||||||
|
%
|
||||||
|
% For a file File that must exist, it returns a time stamp T with the modification time
|
||||||
|
%
|
||||||
|
% T is a time stamp compatible with library(time).
|
||||||
file_modification_time(File, T) :-
|
file_modification_time(File, T) :-
|
||||||
file_time_(File, modification, T).
|
file_time_(File, modification, T).
|
||||||
|
|
||||||
|
%% file_access_time(+File, -T).
|
||||||
|
%
|
||||||
|
% For a file File that must exist, it returns a time stamp T with the access time
|
||||||
|
%
|
||||||
|
% T is a time stamp compatible with library(time).
|
||||||
file_access_time(File, T) :-
|
file_access_time(File, T) :-
|
||||||
file_time_(File, access, T).
|
file_time_(File, access, T).
|
||||||
|
|
||||||
|
%% file_creation_time(+File, -T).
|
||||||
|
%
|
||||||
|
% For a file File that must exist, it returns a time stamp T with the creation time
|
||||||
|
%
|
||||||
|
% T is a time stamp compatible with library(time).
|
||||||
file_creation_time(File, T) :-
|
file_creation_time(File, T) :-
|
||||||
file_time_(File, creation, T).
|
file_time_(File, creation, T).
|
||||||
|
|
||||||
@@ -170,29 +237,27 @@ file_time_(File, Which, T) :-
|
|||||||
read_from_chars(T0, T).
|
read_from_chars(T0, T).
|
||||||
|
|
||||||
|
|
||||||
/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
|
%% path_segments(Ps, Segments).
|
||||||
path_segments(Ps, Segments): True iff Segments are the segments of Ps.
|
%
|
||||||
|
% True iff Segments are the segments of Ps.
|
||||||
Segments is the list of components of the path Ps that are
|
%
|
||||||
separated by the platform-specific directory separator. Each
|
% Segments is the list of components of the path Ps that are
|
||||||
segment is a list of characters.
|
% separated by the platform-specific directory separator. Each
|
||||||
|
% segment is a list of characters.
|
||||||
At least one of the arguments must be instantiated.
|
%
|
||||||
|
% At least one of the arguments must be instantiated.
|
||||||
Examples:
|
%
|
||||||
|
% Examples:
|
||||||
?- path_segments("/hello/there", Segments).
|
%
|
||||||
Segments = [[],"hello","there"].
|
% ?- path_segments("/hello/there", Segments).
|
||||||
|
% Segments = [[],"hello","there"].
|
||||||
?- path_segments(Path, ["hello","there"]).
|
% ?- path_segments(Path, ["hello","there"]).
|
||||||
Path = "hello/there".
|
% Path = "hello/there".
|
||||||
|
%
|
||||||
|
% To obtain the platform-specific directory separator, you can use:
|
||||||
To obtain the platform-specific directory separator, you can use:
|
%
|
||||||
|
% ?- path_segments(Separator, ["",""]).
|
||||||
?- path_segments(Separator, ["",""]).
|
% Separator = "/".
|
||||||
Separator = "/".
|
|
||||||
- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
|
|
||||||
|
|
||||||
path_segments(Path, Segments) :-
|
path_segments(Path, Segments) :-
|
||||||
'$directory_separator'(Sep),
|
'$directory_separator'(Sep),
|
||||||
|
|||||||
Reference in New Issue
Block a user