Simply adding a new file search path

I searched “file_search_path”, found the link to the swish paths.pl module, read it, but I am still bloody well confused as to how to simply add, in my load.pl file, that has an initialization predicate, just how to add the new “./src” and “./test” folders!

I know it’ s probably easy but sometimes the documentation just makes my head spin.
This is another of those times.

I set the prolog flag “verbose_file_search” to true but it didn’t really help. I’ve tried lots of things, this is the current top of my “load.pl” file…

%:- doc_server(4000).
%:- portray_text(true).

% setup my development session

:- multifile user:file_search_path/2.

prolog_set_flag(verbose_file_search, true).
user:file_search_path(app_data, './src').
user:file_search_path(app_data, './test').

:- initialization(setup).

setup :-
    load_test_files([]),
    module(user).

% source files that make should know about
:- use_module(tokeniser).
:- use_module(utils).
:- use_module(ast).
:- use_module(errors).
%:- use_module(coder_base).
:- use_module(options).
:- use_module(keywords).
:- use_module(visitor).
:- use_module(translate).

But all I keep getting is this…

╰─$ swipl load.pl
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:19:
        source_sink `tokeniser' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:19:
        Goal (directive) failed: user:use_module(tokeniser)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:20:
        source_sink `utils' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:20:
        Goal (directive) failed: user:use_module(utils)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:21:
        source_sink `ast' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:21:
        Goal (directive) failed: user:use_module(ast)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:22:
        source_sink `errors' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:22:
        Goal (directive) failed: user:use_module(errors)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:24:
        source_sink `options' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:24:
        Goal (directive) failed: user:use_module(options)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:25:
        source_sink `keywords' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:25:
        Goal (directive) failed: user:use_module(keywords)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:26:
        source_sink `visitor' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:26:
        Goal (directive) failed: user:use_module(visitor)
ERROR: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:27:
        source_sink `translate' does not exist
Warning: /home/sean/Documents/code/prolog/the-f-word-project/load.pl:27:
        Goal (directive) failed: user:use_module(translate)
Welcome to SWI-Prolog (threaded, 64 bits, version 8.0.3)
SWI-Prolog comes with ABSOLUTELY NO WARRANTY. This is free software.
Please run ?- license. for legal details.

For online help and background, visit http://www.swi-prolog.org
For built-in help, use ?- help(Topic). or ?- apropos(Word).


:expressionless:

The idea is rather simple. Files may be specified as Alias(Relative). The typical example is library(lists). The Alias is library, the relative path lists. The aliases are defined using user:file_search_path(Alias, Dir). This should return candidate directories to search for files with the alias Alias. Dir is either a concrete directory or another Alias(Relative) term.

app_data is not for your program. These (and a couple more) provide search paths to find application data, etc. according to the XDG desktop file organization standards.

To make a relocatable application myapp, it is common practice to have the main file setup a file search rule for myapp, pointing at the root directory of the application. You can than find all files as myapp(Relative). You typically use either prolog_load_context/2 to initialise the myapp alias or source_file/2 using a unique predicate in the initial load file:

myapp_version(1.0).

user:file_search_path(myapp, Dir) :-
     source_file(myapp_version(_), File),
     file_directorty_name(File, Dir).

[I like these doc links! thanks @EricGT!

1 Like

Thanks, but don’t forget @jamesnvc and Discourse. They did most of the heavy work I just pointed out that it was possible and help explain which path to take, e.g. the preview button instead of a full install of Discourse.

2 Likes

Thank you @jan I can now load all of my files like I used to, and yes it is simple once you have done it once. :smiley:

I asked for the list of loaded source files, and the bottom of the list are mine,

X = '/home/sean/Documents/code/prolog/the-f-word-project/src/tokeniser.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/keywords.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/utils.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/ast.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/errors.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/options.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/visitor.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/translate.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/coder_base.pl' ;
X = '/home/sean/Documents/code/prolog/the-f-word-project/src/target_c.pl' ;

My problem now is that when I run_tests I only have 18 tests that run…there used to be 80 tests! I have looked at the code for load_test_files with the verbose_file_search:true but it doesn’t emit anything.

How do I instruct the test framework that the files have moved or should that have happened atumatically, the top of my load file now looks like this:

:- prolog_load_context(directory, Dir),
   asserta(user:file_search_path(myapp, Dir)),
   format(atom(S), '~s/src', [Dir]),
   format(atom(T), '~s/test', [Dir]),
   asserta(user:file_search_path(myapp, S)),
   asserta(user:file_search_path(myapp, T)).

Almost there…

I can see that the implementation of load_test_files replaces the .pl with .plt and that’s it. I have also seen that it dynamically creates predicates; test_file_for… I continue to read!

It feels like being Hercule Poriot on the trail of a good case…and once I figure it out it will be a lesson well learned!

Onwards… :hole:

1 Like

So, I think I need to stop thinking like a “conventional” developer i.e. almost all other frameworks I’ve used usually mandate or at least suggest “src” for source files and “test” or “tests” for the test scripts. I know at times like these, when it feels like salmon going upstream, that I have failed to understand something and I think I find the Aha moment, from the docs as usual:

3 Using separate test files

Test-units can be embedded in normal Prolog source-files. Alternatively, tests for a source-file can be placed in another file alongside the file to be tested. Test files use the extension .plt .

So I think that all is well now, I know how to add folders to the search path…it just means that I have to break down the files/folders into, with hindsight(!), a more meaningful way than just “src” and “tests”.

so maybe something like

root
  +-- tokeniser
  +-- ast
  +-- whataver

I can live with that and it actually feels OK.

Typically, I’d use something like this for paths relative to myapp:

user:file_search_path(src, myapp(src)).
user:file_search_path(test, myapp(test)).

There might be some point in exploiting the file search path to find test files. I’m not really sure how though. One could simply load all *.plt files from all files under a test alias? I guess test files do not need a one-to-one relation to source files anyway. The core test system works a little different: it loads all *.pl files from enumerated test directories where each file has a module name equal to the base name of the file that exports a predicate with the same name and arity 0. The test systems loads the file and calls the entry point. That can do whatever it likes. Most use PlUnit, but some do not, either because they predate PlUnit or it didn’t make too much sense.

Ideas welcome. We could also have some main test file that specifies the test configuration and how to find the test files as a set of rules? That could also allow for concurrent testing. Note b.t.w. that you can implement any of the above quite easily using a fairly simple Prolog program on top of PlUnit.

1 Like