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") ...)