upsh.pl -- Unix to Prolog shell.

Upsh 3.0

Upsh stands for Unix to Prolog shell. It is a Prolog program which can be used to run Prolog programs from the command line or as scripts. It originally ran on three Prolog engines without changes to the source code. Current versions are only tested on SWI-Prolog.

With version 3, Upsh has all the features I had envisaged and many which I just thought of on the way. It is also fairly stable and actively maintained. The development has now been switched to SWI and upsh is also provided as an easy to install SWI pack.

The pack has a single main predicate which creates an executable state that provides a convenient way of executing prolog scripts from the command line (cli = command line interaction/invocation). The state can be invoked by calling the created executable (upsh) on command line. By default the upsh binary is placed in same directory as the swipl executable. Only tested on Linux.

Installation and Testing

Install:
?- pack_install(upsh).

This should also create the executable (upsh). The executable can be also be created explicitly with:

?- use_module(library(upsh)).
?- upsh_make.
?- halt.

Ask your shell to re-read its executables with something like rehash, and the upsh executable should be on your path.

> rehash
> upsh say naku
%  /home/nicos/.rcpl compiled 0.00 sec, 8 clauses
% /home/nicos/bin/cline_upsh/say.pl compiled 0.00 sec, 5 clauses
naku

> upsh v
upsh_exec(upsh(3:0:0),swi(10:1:4),built_on(2026/3/9,18:55:45))

Locating Scripts

The executable will look for scripts via the following mechanisms.

Named Scripts

A command line invocation like

> cd $HOME
> upsh say naku
% /home/nicos/.local/share/swi-prolog/pack/upsh/scripts/say.pl compiled 0.00 sec, 6 clauses
naku

names the script say so upsh will look for a prolog file say.pl.

To locate this, upsh will first look in current directory, then in $HOME/bin/cline_upsh/ and finally in PACK/scripts directory of all installed packs. The last of those is how in the above example upsh can locate script say.pl in installed pack $HOME/.local/share/swi-prolog/pack/upsh/scripts/say.pl.

Missing Script Names

When no script name is given upsh will try to infer one.

Select the single .pl file in current directory.

If multiple .pl files exist in current directory select the one that shares its basename with the directory name.

As of v3 users can define a predicate for auto locating scripts in user_profile(upsh_script_sel.pl) defining upsh_script_sel/1 which should return the name of the script.

The idea is that the predicate will look into the current directory and recognise the type of operation that is required.

For instance, in directories with a single .tex file named submit.tex in them, my locator predicate will select the script that runs pdflatex and a pdf viewer on the produced output.

So, in this scenario the user can simply call

> ls
submit.bib submit.tex ....

> upsh

Entry Predicate

Once the input program/script has be loaded, upsh will call the entry predicate possibly passing any OS arguments that are meant for the script as input.

For a program such as, _|say.pl, the default behaviour is to look for defined predicate say/0, say/1, say/n, main/0, main/1, and main/n. It will then call the first of those that is defined and matches any passing arguments. In the case of arity one predicates, if there are multiple arguments to be passed, then they will be passed as a single list.

Argument Passing

Upsh by default converts OS arguments to Prolog terms:

> upsh say a=b
% /home/nicos/bin/cline_upsh/say.pl compiled 0.00 sec, 5 clauses
a(b)

> upsh say a=b,c do=end
a(b,c)
do(end)

> upsh say a=lst=b,c atm=alpha=beta
a([b,c])
'alpha=beta'

\\ escapes elements of construction of terms

> upsh say abc\\=abc a=b\\,c
abc=abc
a((b,c))

To pass term functor =, you can also use ==

> upsh say alpha==beta
alpha=beta

To terminate nested arguments use ":"

άμπελος;upsh/scripts> upsh say a=t=x=y,7 a=t=x=y:7 a=t=x=y::7
% /home/nicos/pl/packs/src/upsh/scripts/say.pl compiled 0.00 sec, 6 clauses
a(t(x(y,7)))
a(t(x(y),7))
a(t(x(y)),7)

Variables can be passed to the script and identified.

> upsh say p a alpha=beta,X gamma=delta=atm=Y
alpha(beta,_1088)
gamma(delta('Y'))
upsh_vs(['X'=_1088])

To avoid translation of Program arguments

> upsh say p o - alpha=beta
'alpha=beta'

To edit the Program source file

> upsh l=e say.pl
or
> upsh say.pl l=e

Upsh flags

The executable takes a number of one letter flags:

hprint help message (and exit)
vshow versions info (and exit)
bverbose, show info on translation of args
psuppresses loading messages
fskip loading initialisation files
e/1direct error messages to file
d/1declares working directory
l/1select loading method
b pass to lib/1
d load (do not call entry)
e edit the target script
l print location of script and exit
m compile
n consult
n/1,2name (and arity) of entry predicate
odo not translate Program arguments
_-_treat remaining inputs as Program args
apass all input variables into last arg
Old functionality
ccommand line invocation
sscript invocation
i/2provider script
t/1script Program
y/2pred to spy-not working due to SWI changes

Pack Information

If you use Upsh for a while I would appreciate an email with the kind of scripts you using it with, at http://stoics.org.uk/~nicos/sware/contact.html

author
- nicos angelopoulos
version
- 2:1 2017/6/3
- 2:2 2018/4/29
- 2.3 2018/5/2
- 2.4 2018/12/10 simplified upsh_make/1 (no more shell call to build the executable).
- 2.5 2019/12/23 work around new SWI configs
- 2.6 2023/11/20
- 3.0 2026/03/09 added user defn: upsh_script_sel.pl, and singleton .pl load in presence of args, redone docs
 upsh_make
 upsh_make(Opts)
Create an upsh executable for running Prolog scripts from command line.

Opts

bin_dir(BinDir=SwiBin)
directory for putting the executable in, defaults to the one holding swipl constructed from current_prolog_flag( home, Home ).
exec(Exec=upsh)
name of executable
author
- Nicos Angelopoulos
version
- 0.1 2017/06/03
- 0.2 2018/12/10

Undocumented predicates

The following predicates are exported, but not or incorrectly documented.

 upsh_version(Arg1, Arg2)
 upsh_version(Arg1)