Sweep: SWI-Prolog Embedded in Emacs

Seems we passed the proof-of-concept state! Looking forward to completion of the wishlist :slight_smile:

I warmly recommend this mode for Emacs users. As addict of the builtin editor I still feel a little handicapped. Often, this is because I got a little out of sync with Emacs after using the builtin version for so long. The editors are fairly compatible but there are subtle differences. I assume that a few setting and re-learning some old habits I’ll be a happy sweep user.

Thank you, Jan!

One thing I forgot to mention in my previous post: now that the Elisp package is included in a standard packages archive, it can be installed in Emacs with M-x package-install RET sweeprolog RET.
This is the recommended way to install sweep, as it will also install the sweep manual in Info format.
To open the sweep manual inside Emacs type C-h i d m sweep RET (also available online at sweep: SWI-Prolog Embedded in Emacs). I recommend looking through the manual to get an idea of the available features.

Cheers

The installation should probably describe the need for LD_PRELOAD on some systems. Not sure on which. Probably at least on systems with ELF format binaries (Linux and various other POSIX systems) using Emacs older than version 29. I use a script emacs in ~/bin holding

#!/bin/sh

LD_PRELOAD=~/src/swipl-devel/build.pgo/src/libswipl.so /bin/emacs "$@"

One should be warned that Prolog is loaded as a shared object into the Emacs process. If Prolog crashes hard it will take down the editor :frowning: The sweeprolog-restart de-initializes Prolog and re-initializes it. This works mostly fine in recent versions although the restart cycle does leak memory if various extension packages are used.

Has the build process changed when building the package from the repo (I use straight.el to manage emacs packages)? I see that now the Makefile has been replaced with CMakeLists.txt, but trying to run cmake . gives an error:

CMake Error at CMakeLists.txt:4 (include):
  include could not find requested file:

    ../cmake/PrologPackage.cmake


CMake Error at CMakeLists.txt:16 (swipl_plugin):
  Unknown CMake command "swipl_plugin".

If you’re building SWI-Prolog from the git repository, you shouldn’t have to build the sweep native module manually, as it is built along with swipl, and the Elisp side of sweep knows how to locate it from where it is installed by the build process.
The sweep repository is included as a submodule of the SWI-Prolog repository (swipl-devel), and that CMakeLists.txt is currently only usable as part of building the entire SWI-Prolog system, as you noted.
The sweep repository also contains the sweeprolog.el Elisp library and the sweep manual, which are not installed by SWI-Prolog. Can you instruct straight.el to only install them from the repo?

BTW maybe it would be a good idea to make the CMakeLists.txt work also independently and build sweep-module, so people can install sweep manually without building SWI-Prolog from source, I’m not sure though.

Added a note about that to the manual under Getting Started.

Also added a toolbar menu that appears in sweeprolog-mode buffers with some useful commands, to assist new users with discovering features:

1 Like

Ah, so I just need to install a newer version of swipl itself and the module is included as part of that? Excellent; I’ll give that a try. I can indeed tell straight to just install the elisp – the errors were just because I still had set it to call make as part of the build process.

Yes. Building foreign modules is not easy on some platforms. The whole setup to get this done is part of the normal build process anyway.

2 Likes

Hm, I just built the latest swipl-devel master and pulled the latest sweeprolog.el into my emacs (29.0.50), but opening a prolog file doesn’t get any highlighting; C-c C-l gives Loading foo.pl failed, C-c C-t gives Failed to create new top-level!. Nothing in *Messages* or *sweep Messages*

Just doing an incremental build doesn’t seem to include the new package. I guess you did to git submodule update --init? Next step I did was to delete CMakeCache.txt and re-run cmake and ninja/make. That should create the shared object in packages/sweep/ below the build directory.

I did get the module built and it seems to be located correctly – sweeprolog--ensure-module runs successfully – but clearly something isn’t quite working…

It looks like running queries are failing – for example, when running (sweeprolog-current-prolog-flags), the “solutions” I get look like this:

(exception compound "error"
  (compound "existence_error"
    (atom . "procedure")
    (compound ":" (atom . "system")
      (compound "/" (atom . "$notrace") 2)))
  (compound "context"
    (compound ":" (atom . "system")
      (compound "/" (atom . "$c_call_prolog") 0))
    variable))

I really like the builtin editor. It is extremely fast and it shows documentation easily, it is --as expected-- extremely well integrated with the whole development cycle of a prolog application. Just seeing the speed and the versatility of it is what got me interested in playing with xpce. SWI-Prolog never ceases to amaze me as to what is included in it.

One of the features I really like are the automatic build of exports for the module with just a keystroke, and also the automatic adding of :-use_module(…) or :- autoload(…) with another keystroke.

1 Like

Thanks for digging into it, seems like you’re getting an existence_error for system:'$notrace'/2.
I’m not sure how that happens to be the case as this predicate is defined in C in libswipl… Just to make sure, does the regular swipl top-level work as expected for you with this build?

One of the items on my todo list for sweep is providing better access to Prolog documentation (both PlDoc comments and the SWI-Prolog manual). May I ask how do you currently view documentation in the built-in editor and whether there are any features that’d make your life easier in that area?

That is very strange…yup, running swipl directly works as expected.

To view the documentation you put the cursor on the predicate, right click on it and the popup menu has an entry called “Documentation”.

But really the most useful things I find are the automatic update of :- use_module(.., ..)/autoload entries, and the easing of cursor movement when writing docs for a predicate. You can see these in action by loading some piece of code you have (which uses imports), delete all the use_module entries (leave the cursor there) and choose from the menu: Prolog>Update dependencies. You will see it nicely populating all the imports. For writing predicate docs type %% at the beginning of a line.

I sometimes also use the Prolog>Make module menu.

What I would find really useful is to have a write-pldoc-header command that would automatically write:

%! closest_predicate_below_cursor(Arg1,Arg2,Arg3).
%
%  <cursor_left_here>

for the closest predicate below the cursor. I normally use vim or neovim with @jamesvnc lspserver to write the code, and I switch to the builtin editor to update the imports (use_module...) and to write the predicate documentation. Often when I am debugging I stay with the builtin editor and press C-X C-s C-X C-m to save and run make.

Really the perfect editor for me would be the builtin editor with vim keybindings :smiley:

I have a function in my emacs config for making the pldoc comment here, if that’s of interest to you…(and, above that, a function to make it easy to manually insert a use_module entry. it occurs to me that doing so automatically shouldn’t be that hard either…)

1 Like

Very strange indeed. A bit of a shot in the dark but I saw in the Emacs config you’ve linked to that you had sweep-swipl-path set to a custom location, maybe that wasn’t updated to sweeprolog-swipl-path?

Well, $notrace/2 was recently added to arrive at a notrace/1 implementation that did not involve a callback over C and (thus) stops yield to work and as a result caused several toplevel predicates in the WASM version not to work. Many toplevel predicates such as make/0, edit/1, spy/1, etc are wrapped in notrace/1 such that you do not start tracing their implementation when the toplevel is in trace mode.

So, my suspicion is that when loading into Emacs you load an old version of libswipl.[so/dylib/dll].

1 Like