Alire: how to find the spec files of imported libraries

If I want to use a library in my alire project I do a alr with fancylib, for example. In the editor (Emacs with ada-ts-mode) I have to look up some of the details of fancylib’s interface. I usually first try to find some specs on Github in a parallel browser window and eventually I have to get a parallel copy of the lib just to open the files in Emacs (i.e. cd ..; alr get fancylib, then in Emacs open the spec file at ..\fancylib_xxxx\src\fancylib.ads).

I have the feeling that there must be an easier way to find the spec files for a withed (i.e. imported) library, a way that is not tied to a special environment (Emacs ada-ts-mode, VS code, GPS, etc.)

I use a vim-like editor with enabled support for ada-language-server.

When I import a package from alire repository, the language server lets me inspect the imported declarations and implementations with single keystrokes.

Those imports are stored under $cache.dir/builds/, where cache.dir[1] is alire’s storage directory that defaults to ${XDG_DATA_HOME:-$HOME/.local/share}/alire on Linux/macOS and $LocalAppData\alire ($UserProfile\AppData\Local) on Windows.

I used to be an Emacs poweruser and I’m sure it has good support for LSP. The language server is sure to be supported and offers all the ergonomics you need to quickly browse the sources. If you don’t use the language server, you could write a simple elisp function that opens a dired buffer in cache.dir or even searches the cache.dir for relevant package sources.

[1] alire/src/alire/alire-platforms-folders.ads at 7507d3fff57dfa4916e81aa80a876e9cb1e06908 · alire-project/alire · GitHub

I recorded a short video showing how effortless getting to the library source is with ada-language-server:

2 Likes

Is there a direct link to the video? It doesn’t appear to be a supported MIME type for the browser (at least on this end).

You should be able to right-click and open in another tab?

Here’s the link:

https://files.catbox.moe/966rn3.mp4

1 Like

Thanks. I’ll play with that and see if I can get it working. I wasn’t able to right click the one in the earlier post as Firefox didn’t even try to load it due to the MIME type issues, so no right click save/as.

I’m happy where it stands, it’s really well done and works with helix (the editor I use).

~
As for Emacs, I haven’t used it for some time, but if I were going to, I’d start by installing lsp-mode and ada-ts-mode.
The only question is how well do they cooperate with alr and ada_language_server to extract the information necessary to find library imports…

I took a moment to see how Ada language server and alire work with Emacs.

Tl;dr: https://files.catbox.moe/jucccv.mp4

Notes:

  1. From a vanilla Emacs 29.4 to mostly working setup
  2. Exact setup steps are illustratory, every emacser knows best how to configure the editor
  3. For reasons unknown, lsp-mode bombarded me with warnings - so I increased the minimum warning level.
  4. There is a ~20s compilation process for lsp-mode package around 1m20s timestamp. This thing seems to download and compile all the available LSPs. This is bad, perhaps something can be done.
  5. The lsp-mode does not automatically detect the correct project root for me - so I modify it with option ‘I’ when I open a file in src/. The alternative is to use M-x lsp-workspace-folders-add in the project directory, or perhaps(?) to configure the lsp-mode to detect properly.

This works as shown in the video, assuming ada_language_server and alr are in PATH (though I think lsp-mode supports installing the language server automatically).

~

I also realised that the original question was really about alire and it wouldn’t hurt to have an alr project-level subcommand that lists all the dependencies with optional switch for pringing paths in cache.dir. In unixy systems we could then just invoke alr with --paths | grep 'libhello' | xargs vim. Assuming that alr with already fetches the sources and stores them in cache.dir, I see no reason why we should need to alr get them separately.

If anyone’s interested in automating getting to alr with-ed sources without the ada_language_server, the paths of libraries are available through alr printenv[1].

Then, for unix-like systems we can do whatever we want with it:

#! /bin/sh -
#
# hard-dependencies: alr, awk
# soft-dependencies: wl-clipboard (or xclip/xsel), fzf, etc.

set -eu

crate="$1"
dir="$(alr -n -q printenv | awk -F'"' -v ere="^export ${crate}_alire_prefix=" \
   'tolower($0) ~ ere { print $2 }')"

if [ ! -d "$dir" ]; then
   printf 'Crate directory does not exist:\n   %s\n' "$crate" >&2; exit 1
fi

src="${dir}/src" # exclude build/config files
if [ ! -d "$src" ]; then
   printf 'Source directory does not exist:\n   %s\n' "$src" >&2; exit 2
fi

## Print path to crate sources
printf '%s source files at:\n   %s\n' "$crate" "$src"

## Copy path to crate source files to clipboard
# wl-copy "$src" && printf 'Source path copied to clipboard:\n   %s\n' "$src"

## Open a selected file
# find "$src" -type f -name "*.ad[bs]" | fzf | xargs "$EDITOR"

One limitation:
alr printenv is project-specific so this cannot be used to go to non-alr with-ed sources even if they do exist.
For that, write a more general script that simply searches the alire cache.dir, e.g.

#! /bin/sh -

set -eu

crate="$1"
alire_cachedir="${XDG_DATA_HOME:-"${HOME}/.local/share"}/alire/builds"

## Print path to crate directory
find "$alire_cachedir" -type d -name "${crate}*"

[1] how to get a remote crate's SOURCES (adb/ads files) · Issue #1737 · alire-project/alire · GitHub

Actually, if I understand correctly, the first script is not general enough: the sources may not be in src; to be fully general you have to check Sources_Dirs in the gprbuild project file.

It is not general, but whether it’s general enough depends on the user.

The functionality you mention isn’t trivial (is there always “Source_Dirs” entry in project.gpr? can it be empty? can it have 3 fields? more? always 2?). Now that you’d decided you know the answers and can depend on them, have fun extracting the correct field(s) from the gpr file.

I think a simpler approach has its merits

set -- src source custom_src_dir
for dir; do
   if [ -d "$dir" ]; then
      ## print or copy or find
      printf '%s source files at:\n   %s\n' "$crate" "$dir"
      break; ## or not
   fi
done

PS:
If big projects can use multiple source subdirs, then I would just find all the ‘*.ad?’ files (including noise such as config/*_config.ads) and be done with it.

This is from one of my crates:

for Source_Dirs use ("config", "src/c", "src/bindings", "src/devices", "src/interfaces", "src/objects/**");

I just duplicated my own code tree when I created the crate.

Here we have only one source directory src/, but it does illustrate the difficulty of making a shell script extract such information.
The original objective was to find out where Ada sources are for a library imported with alr with (so we also want to ignore the "config" dir).
It is very easy to extract the library/crate subdirectory in the alire cache.dir, but it is not so easy to go further than that if we want to do minimum work.
Extracting source directory names from the project’s gpr file is not a job for awk or any unix tools (there’s gprls, but it does not seem script-friendly).

All in all, I think a script that takes a crate name and prints directories in alire cache matching that name is as simple and as general as one can hope.