# Command line scripts

**URL:** <https://swi-prolog.discourse.group/t/command-line-scripts/6924>\
**Category:** Request For Comments\
**Created:** [October 27, 2023, 10:17am UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924 "2023-10-27T10:17:03Z")\
**Posts on this page:** 10\
**Page:** 1

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 27, 2023, 10:17am UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/1 "2023-10-27T10:17:04Z")

</div>

Following [How to call a predicate with arguments from command line and output its solution?](https://swi-prolog.discourse.group/t/how-to-call-a-predicate-with-arguments-from-command-line-and-output-its-solution/6919) and [Symbolic links and real file names [mainly Windows Platform]](https://swi-prolog.discourse.group/t/symbolic-links-and-real-file-names/6887) and considering that in XSB the command line `xsb name` runs `name.P` from its library and considering that `swipl name` is simply an error, I think there is room for some improvement.

First, I was suggesting `-m name`, similar to Python. I think that can be simpler and cleaner. Right now, I’m considering

```
 swipl [pl-option ...] [search-path:]name ...

```

to mean load `search-path(name)` and make … available as `argv`. As there are a lot of files in the library search path and most are unsuitable for using this way as they do not process commandline arguments, I propose a new search path `apps` that would default to swi(apps) and allow each package to add apps. So we can make

```
 swipl pack ...
 swipl query ...

```

… etc. This approach easily runs on any platform. Just using the defaults would allow big apps to be compiled to `.qlf`. We could also define an extension such that we can create saved states in the app dir for fastest startup.

Normally, such a script should use this to get started

```
:- initialization(mystart, main).

```

I wonder what to do if this is missing. One option could be to simply start the normal REPL, another to simply terminate or complain that it doesn’t know how to start? Just dump into the REPL loop of course allows you do to e.g.

```
  swipl library:scasp

```

which would be nice for libraries that are not autoloaded but you may want to use interactively.

Opinions? Improvements? Other options?

---

<div class="post-metadata">

**Author:** ![joeblog](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/joeblog/32/122_2.png) [@joeblog](https://swi-prolog.discourse.group/u/joeblog)\
**Post date:** [October 27, 2023, 3:55pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/3 "2023-10-27T15:55:07Z")

</div>

I’ve written a couple of Unix filters using SWI-Prolog, and found the “Convert a CSV with column names to JSON” example in the documentation at [SWI-Prolog -- (initialization)/2](https://www.swi-prolog.org/pldoc/man?predicate=initialization/2) really helpful.

While using `< inputfile myfilter.pl` rather than `myfilter.pl inputfile` works fine using the example as a template, I haven’t figured out how to get `myfilter.pl <<<$output_from_last_filter` to work in SWI-Prolog.

So a way to write PrologScript files that meet all the “standard” Unix filter conventions would be great. I suspect it probably can already be done, I just don’t know how.

---

<div class="post-metadata">

**Author:** ![paule32](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/paule32/32/5112_2.png) [@paule32](https://swi-prolog.discourse.group/u/paule32)\
**Post date:** [October 27, 2023, 4:12pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/4 "2023-10-27T16:12:52Z")

</div>

under Windows, there are Named Pipes, you can use.  
I come from the Linux Fraction, but used Windows at this Time.  
I have install the MSYS2 MinGW32- / 64-Bit Environment - This is like Cygwin a Emulatetion of the BASH Shell with some Tools that you know from the Command Line under the Linux Terminal.  
You can use this Shell, if you want to automate Things (like using your Filters - that are in my Eyes are Tools that you send over Pipes like: # echo “hello world” | awk ‘{print $2}’ which bring as Result: # world on Terminal Display Device.  
Feel free for asking…

---

<div class="post-metadata">

**Author:** ![swi](https://avatars.discourse-cdn.com/v4/letter/s/51bf81/32.png) [@swi](https://swi-prolog.discourse.group/u/swi)\
**Post date:** [October 27, 2023, 5:39pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/5 "2023-10-27T17:39:47Z")

</div>

> [@jan](#):
>
> ```prolog
> :- initialization(mystart, main).
> 
> ```
> 
> I wonder what to do if this is missing. One option could be to simply start the normal REPL,

I think starting the REPL will not be good, because the end user is expecting it to behave just like a normal command line program. So the proper option, imho, is to exit with an error message and and exit code different from 0 just like all command line programs normally do.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 27, 2023, 5:55pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/6 "2023-10-27T17:55:17Z")

</div>

> [@jan](#):
>
> `-m name`, similar to Python

Just to clarify: `swipl -m name` would be essentially the same as `swipl $(swipl-lookup name)`, where `swipl-lookup` is

```plaintext
swipl -g "absolute_file_name(library(name), X, [access(read), file_type(prolog)]), writeln(X)" -t halt

```

?

BTW, the “man” page for `swipl` could do with some cleanup … there doesn’t seem to be an obvious order to the various options and I find it difficult to find an option, even when I know the feature that I’m looking for. (Are there any tech writers in this group?)

> [@swi](#):
>
> [if `initialization(mystat, main)` is missing] I think starting the REPL will not be good,

Agreed. Python has an implicit “main” (usually with an `if __name__ == ' __main__'`); C/C++ requires a `main()` function, etc.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 27, 2023, 9:25pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/8 "2023-10-27T21:25:01Z")

</div>

> [@jan](#):
>
> considering that `swipl name`

Why not treat the `name` the same way that load\_files/2 does? So, you could write `swipl ... 'library(name)'` without the need for a `-m` option. (Although it might look a bit strange to non-Prologers). From looking at the default settings for file\_search\_path/2, it seems that only `library` is meaningful for loading files (perhaps `pack` also?), so treating `name` as whatever absolute\_search\_path/2 gets for `name` or `library(name)` might make sense (or might be confusing, which is possibly why Python has `-m`).

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [October 29, 2023, 12:34pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/10 "2023-10-29T12:34:54Z")

</div>

> [@peter.ludemann](#):
>
> Why not treat the `name` the same way that [load\_files/2](https://www.swi-prolog.org/pldoc/doc_for?object=load_files/2) does?

That is more or less what I propose. `swipl [search-path:]name` uses the same logic as `load_files(SearchPath(Name))`, where I propose `app` as default search path. From there on, there are few choices (I hope). Basically only how we call “main”? As we already have initialization/2 of “kind” `main`, I propose to use that. Applications that wish to run the Prolog REPL loop can do so explicitly from the initialization/2 goal. See library(main).

This still requires `swipl` in from of the cli command. That is a bit of a pity. It does provide platform independence, make it easy to add cli commands to control the Prolog environment, allow packs to add new cli commands, etc. And, it does all that without requiring the user to adjust `PATH`, create directories, etc.

---

<div class="post-metadata">

**Author:** ![peter.ludemann](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/peter.ludemann/32/48_2.png) [@peter.ludemann](https://swi-prolog.discourse.group/u/peter.ludemann)\
**Post date:** [October 29, 2023, 4:21pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/11 "2023-10-29T16:21:27Z")

</div>

> [@jan](#):
>
> This still requires `swipl` in from of the cli command

Python programs still require `python` (or `python3`) in front of the CLI commands, so I don’t see this as a big problem. And there’s always qsave\_program/2, if you want to get rid of the `swipl`.

---

<div class="post-metadata">

**Author:** ![nicos](https://avatars.discourse-cdn.com/v4/letter/n/7feea3/32.png) [@nicos](https://swi-prolog.discourse.group/u/nicos)\
**Post date:** [November 20, 2023, 12:18pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/12 "2023-11-20T12:18:20Z")

</div>

Hi Jan,

pack(upsh) has a few relevant features.

upsh Lib:Pred  
will load library(Lib) and call ?- Pred. (or Pred(ListOfArgs))

The mechanism you propose is more general, but looses a bit of the simplicity. My private code is either simple enough to be a single script which goes to ~/bin/cline\_upsh or complex enough to go to a pack dir, which remains private until it is mature enough to go public. Bottom line is, there is no need to use anything else apart from packs 🙂

You could go “more abstract” by creating a registry of Preds in Libs and do away with Lib: but I never felt a need for that relating to scripts. pack(lib) does utilise these if they exist, but in the end i switched to breaking interface preds of a pack into their own file, so it is trivial to locate them by looking at pack/src/\<pred\_name\>.pl . (A complex enough example is pack(stoics\_lib).)

upsh will also load Local.pl if this is the only .pl file in current dir (you could have a new flag or modify behavior of -f -l )

upsh Script.pl  
also looks at script locations to find Script.pl  
~/bin/cline\_upsh/  
and Pack/scripts/  
[For Pack in all installed packs.]

In addition upsh will convert args from cli friendly to Prolog terms args.  
Finally my upsh scripts that take os objects as args take the convention that atomic args are files to operate on, while Options that modulate behaviour are terms (eg prefix=testo at cli, which is translated to prefix(testo) in the Prolog call).

Regards

## Nicos Angelopoulos

> **[Nicos Angelopoulos](https://stoics.org.uk/~nicos/)**
>
> logic programming

> **[Upsh: Unix to Prolog SHell](https://stoics.org.uk/~nicos/sware/upsh/)**

---

<div class="post-metadata">

**Author:** ![jan](https://yyz2.discourse-cdn.com/free1/user_avatar/swi-prolog.discourse.group/jan/32/4_2.png) [@jan](https://swi-prolog.discourse.group/u/jan)\
**Post date:** [November 20, 2023, 3:18pm UTC](https://swi-prolog.discourse.group/t/command-line-scripts/6924/13 "2023-11-20T15:18:04Z")

</div>

> [@nicos](#):
>
> upsh Lib:Pred  
> will load library(Lib) and call ?- Pred. (or Pred(ListOfArgs))

This is indeed a very simple design that deals with a large subset of the cases and allows for multiple toplevel goals per file. As you say, it is also a bit more limited, notably in commandline parsing.

> [@nicos](#):
>
> upsh will also load Local.pl if this is the only .pl file in current dir (you could have a new flag or modify behavior of -f -l )

Many commands have stopped loading some file from the current directory for security reasons. Also SWI-Prolog used to load `.plrc` from the current dir long ago. Of course, there are still exceptions such as `make`. They _require_ a file in the current directory though.
