Initing

Run

schubert init

Schubert then will ask you for the packager of library/program, most propably your name/nickname, the name of the libary/program and the license.

If you started with empty directory, after running this command it's structure should look like this:

.
├── composition.scm
└── your-name
    └── library-name
        └── version
            └── main.scm

and the contents of composition.scm should look like this:

((packager . "your-name")
  (name . "library-name")
  (version . "v0-1-0")
  (description . "Remember to change this")
  (license . "LIBRARY-LICENSE")
  (dependencies)
  (development-dependencies)
            )

And the contents of your-name/library-name/version/main.scm looks like this:

(define-library
  (your-name library-name version main)
    (import (scheme base)
            (scheme write))
      (export main)
        (begin
            (define main
                  (lambda ()
                          (display "Hello world")))))

When Schubert installs the libary the "version" in the path and library name is replaced with the version in the composition.scm.

Searching for libraries

Run

schubert search KEYWORD

to search for libraries.

To see what repositories are searched see the search index.

Adding a dependency

Using schubert depend

Run

schubert depend PACKAGER LIBRARY-NAME

for example:

schubert depend retropikzel string-util

Schubert will search for the library from repositories in the search index.

If library is found Schubert will ask you if you want to add it into the composition.scm after which the contents of composition.scm should look like this:

((packager . "your-name")
 (name . "library-name")
 (version . "v0-1-0")
 (description . "Remember to change this")
 (license . "LIBRARY-LICENSE")
 (dependencies ("https://git.sr.ht/~retropikzel/schubert-repository-r7rs-small" (retropikzel string-util v1-0-3 "ac2e0d39b6b351c9d2454e45777622b25fe03ed3"))))

Shucbert will fetch the latest version and add a hash so when the library is downloaded it can be checked.

Manually

To add a dependency into your project add list like this

("https://git.sr.ht/~retropikzel/schubert-repository-r7rs-small" (retropikzel string-util v1-0-3 "ac2e0d39b6b351c9d2454e45777622b25fe03ed3")))

into your composition.scm under dependencies.

After that your composition.scm should look like this:

((packager . "your-name")
  (name . "library-name")
  (version . "v0-1-0")
  (description . "Remember to change this")
  (license . "LIBRARY-LICENSE")
  (dependencies
    ("https://git.sr.ht/~retropikzel/schubert-repository-r7rs-small"
        (retropikzel string-util v1-0-3 "ac2e0d39b6b351c9d2454e45777622b25fe03ed3"))))

Not that the hash is optional.

You can get the hash running:

git ls-remote --tags LIBRARY-REPOSITORY-URL

Note that the repository url in the composition.scm is schubert repository, not the librarys git repository.

Note that the hash is not checked yet as it's work in progress and when implemented, only checked if it exists and on library download.

Adding a development dependency

Using schubert development-depend

Run

schubert development-depend PACKAGER LIBRARY-NAME

it works same as the depend command, it just puts the library into the development-dependencies list in the composition.scm.

Manually

To add a dependency into your project add list like this

("https://git.sr.ht/~retropikzel/schubert-repository-r7rs-small" (retropikzel string-util v1-0-3 "ac2e0d39b6b351c9d2454e45777622b25fe03ed3")))

into your composition.scm under development-dependencies.

Composing your project

After adding your dependency, run

schubert compose

and let schubert do its thing. After the command has run the directorys structure should look like this

.
├── composition.scm
├── schubert
│   └── retropikzel
│       └── string-util
│           └── v1-0-3
│               ├── composition.scm
│               └── main.scm
│               └── main.sld
│               └── main.rkt
└── your-name
    └── library-name
            └── version
                └── main.scm

The dependencies are installed in the "schubert" folder. When running your program you should add this folder into the load path of your scheme implementation.

Note that Schubert makes .sld and .rkt files in addition to the .scm file for compability reasons and you should always use .scm as file ending.

Note that use of include is also discouraged, as the include paths are different on different implementations and it's use can introduce imcompalibilities.

For example Kawa does not support .sld files, Cyclone does not support .scm files and racket only supports .rkt files. The situation is not ideal so Schubert tries to mitigate it.

I do not remember the inconsistencies with include anymore, I've stumbled to them so many times that I gave up on using it some time ago.

Composing development dependencies

It works the same way as regular compose but the command is:

schubert development-compose

Not that development dependencies are install into same directory as regular dependencies.

Using the libraries

To use the libraries, import them into your program. Here is an example hello.scm

(import (scheme base)
        (scheme write)
        (retropikzel string-util v1-0-3 main))


(write (string-util-split-by-char "Hello world" #\space))
(newline)

Note that we import the main.scm from retropikzel/string-util/v1-0-3 directory and the import is different from the dependency definition in composition.scm.

Then run hello.scm

With Guile

guile -L ./schubert hello.scm

With Sagittarius

sash -L ./schubert hello.scm

Working with/installing libraries locally

I find myself often working with two or three libraries and a program that uses them. For this situtation schubert has a command "install". Which installs the library into local cache, for schubert compose command to use.

Lets say you have libraries A and B, and program C that uses them. For C to be able to use the libraries they do not have to be in repository, it is enough to install them locally.

To do this navigate into the library A directory and run

schubert install

and navigate into the library B directory and run

shubert install

Your dependencies in program C's composition.scm should look something like this.

...
(dependecies
    ("default"
        (PACKAGER A VERSION)
        (PACKAGER B VERSION)))
...

then in program C directory run

schubert compose

and schubert directory structure should be after that something like this

.
└── PACKAGER
    ├── A
    │   └── VERSION
    │       ├── composition.scm
    │       └── main.scm
    └── B
        └── VERSION
            ├── composition.scm
            └── main.scm

you do not need to change the version of your library, running schubert install will overwrite the library directory in local cache and schubert compose command will overwrite the ibrary directory under ./schubert

Generating documentation

Shubert is able to generate mkdocs combatible documentation for library exports. Run

schubert document

in projects root folder. Schubert will create directory named docs and files mkdocs.yml and file under docs directory for each library file in PACKAGER/NAME/VERSION path in your projects root.

To see the documentation locally run

mkdocs serve

for more information about how to, for example generate documentation website, see mkdocs getting stared documentation

Return type

You can add the return type of exported procedure by adding

;-> type

to the end of the same line that has the define keyword and the procedure name.

Examples:

(define plus ;-> number
  (lambda (x y)
    (+ x y)))

(define (plus) ;-> number
  (+ x y))

(define-record-type point
  (make-point x y)
  point?
  (x point-x-get point-x-set!)  ;-> number
  (y point-y-get point-y-set!)) ;-> number

Note that return type comments for records are for field getters only, return type of unspecified is automatically added to setters if they are exported.

Docstrings

Procedures

You can add docstring to the exported procedure by adding a start of #| |# comment on the line after that has the define keyword and procedure name.

Examples:

(define plus ;-> number
  #| Adds two numbers together |#
  (lambda (x y)
    (+ x y)))

(define (plus) ;-> number
  #| Adds two numbers together |#
  (+ x y))

Records

You can add docstring to the exported record and it's procedures by adding a start of #| |# comment on the line after that has the define-record-type and record name or procedure name.

(define-record-type point
  #| Record point that holds x and y coordinates |#
  (make-point x y)
  #| Create a new point record |#
  point?
  (x point-x-get point-x-set!)
  #| Get the x value of the point |#
  (y point-y-get point-y-set!))
  #| Get the y value of the point |#

Adding your library to a repository

For updated list of Schubert repositories you can check out the search index repository at https://git.sr.ht/~retropikzel/schubert-search-index

See if your library matches the requirements of the existing repositories, if not you might want to create your own repository and make a pull request to add it into the index.

Creating new repository

Schubert repositories are git repositories that contain libraries.scm file with content:

((PACKAGER NAME "GIT URL" "DESCRIPTION") ...)