# -*- mode: org -*-

                                             Good morning, Maeve.
                                                  -- Hall 9000

Welcome to Hall!

Hall is a command-line project manager for projects written in GNU
guile.  It is also a set of libraries for interacting with Guile
projects.

* Table of Contents

  1. [[*Introduction][Introduction]]
  2. [[*What's in the box?][What's in the box?]]
  3. [[*Getting Started][Getting Started]]
  4. [[*Development Notes][Development Notes]]

* Introduction

Hall aims to provide a black box that "just works" (tm), so that you
can create, develop, build & distribute Guile projects.

With Hall you will be able to:
- Manage a Guile project hierarchy from one project spec file.
- Transparently support the GNU build system for maximum portability.
- Leverage tight coupling to Guix for reliability & confidence.
- Profit.

This README is all written documentation that currently exists.  The
project must be considered Alpha software at this stage.

Nonetheless, all commands and arguments are documented, and passing
the -h flag to any command or sub-command should provide you with some
guidance.  In addition all procedures in the codebase are documented
with docstrings.

* What's in the box?

  This section details some basic usage examples of Hall.  If you are
  interested in reading a full tutorial, [[https://write.as/jeko/hall-a-project-manager-for-the-guile-programming-language][check out Jérémy Korwin-Zmijowski
  post]]!

** Creating a New Project

   #+BEGIN_SRC bash
     cd /to/some/directory/
     hall init --author "Jane Doe" frobnigator --execute
     # Creating project: frobnigator
     # ...
     cd frobnigator
     # Do some hacking
     emacs hall.scm # Add other Guile dependencies
     # Add new files to our hall.scm
     hall scan
     # Dryrun:
     #...
     hall scan -x # Add new files.
   #+END_SRC

** Converting an Existing Project

   #+BEGIN_SRC bash
     cd /to/some/guile-project/
     hall init --convert --author "Jane Doe" --prefix guile frobnigator --execute
     # Creating project: guile-frobnigator
     # ...
     emacs hall.scm # Add other Guile dependencies, and tweak project settings.
     # Add new files to our hall.scm
     hall scan
     # Remove cruft
     hall clean
   #+END_SRC

** Getting Ready for Distribution

   #+BEGIN_SRC bash
     # Get ready to test commandline or distribute:
     hall dist -x # create the build infrastructure

     # Oops, we made a mistake
     #
     # WARNING
     #
     # The clean command is destructive - it will remove not only infrastructure files
     # as created by the dist command above, but also any other files, including source
     # files, that hall does not know about.
     # You can register new files with Hall by using the scan command.
     #
     # WARNING
     #
     hall clean -x # undo previous step

     # Let's re-generate the guix file.
     rm guix.scm && hall guix -x # re-generate guix file

     # Now let's create the build infrastructure
     hall dist -x # recreate build infrastructure

     # Let's build it!
     guix environment -l guix.scm
     autoreconf -vif && ./configure && make && exit

     # Let's run it!
     ./pre-inst-env guile # Here we can load our local libraries!
     ./pre-inst-env scripts/${script} # Or run our scripts

     # We're ready for a tarball
     guix environment -l guix.scm
     make dist
   #+END_SRC

* Getting Started

                                    Look Dave, I can see you're really
                                      upset about this.
                                                  -- Hall 9000

  In general, Hall uses the autotool infrastructure.  This *should*
  make installation straight-forward.  There are two ways to get Hall
  up and running:

** Using Guix

   This is the preferred approach.  If you haven't tried [[https://gnu.org/s/guix][guix]] yet you
   should definitely givet it a go!  Once you have Guix installed all
   you need to do is run `guix package -i guile-hall`.

** Using Autotools

   This is somewhat more manual.

   First, you will need to make sure you have autoconf, automake
   pkg-config, guile, git and texinfo installed.  How to do this
   depends on the distro you are using.

   Once you have these installed, you are ready to install
   guile-config and then guile-hall.

   Below are the instructions for all of this on Debian.  Very similar
   instructions should work on Debian derivations.

   #+BEGIN_SRC bash
     # Install the dependencies
     sudo apt install autoconf automake pkg-config \
              texinfo guile guile-2.0-dev git

     # Clone the guile-config repository & cd
     git clone https://gitlab.com/a-sassmannshausen/guile-config
     cd guile-config

     # Install guile-config by doing the Autotools dance!
     autoreconf -vif && ./configure && make check
     sudo make install
     cd ..

     # By default guile libraries will be installed in /usr/local/
     # so we must set the environment variables
     export GUILE_LOAD_PATH=/usr/local/share/guile/site/2.0/
     export GUILE_LOAD_COMPILED_PATH=/usr/local/lib/guile/2.0/site-ccache/

     # Now we can install guile-hall
     # Clone the repository & cd
     git clone https://gitlab.com/a-sassmannshausen/guile-hall
     cd guile-hall

     # Autotools dance!
     autoreconf -vif && ./configure && make check
     sudo make install

     # The application will be installed in /usr/local/bin/
     # If hall --version does not work, try:
     export PATH=/usr/local/bin/:${PATH}

     # Now you can run hall!

     hall --version

     # To make the above permanent, you could add the commands to your
     # ~/.bashrc:
     echo export GUILE_LOAD_PATH=/usr/local/share/guile/site/2.0/ >> ~/.bashrc
     echo export GUILE_LOAD_COMPILED_PATH= /usr/local/lib/guile/2.0/site-ccache/ >> ~/.bashrc
     echo export PATH=/usr/local/bin/:${PATH} >>~/.bashrc
   #+END_SRC

* Development Notes

                                    Work, work, work, work, work, work
                                                  -- Rihanna

  Below you will find some unfiltered development nodes that have
  served me while developing Hall.  In the presence of as of yet
  rudimentary documentation, you may find these notes enlightening.

** Next Steps

   - [X] Need following sections under files:
     + libraries
     + tests
     + programs
     + documentation
     + infrastructure
   - This is to generate the Makefile etc.

   - [X] Should generate filetypes as part of 'write operation:
     + .scm -> scheme-file
     + .sh -> shell-file
     + .texi -> texi-file
     + retain 'file' as fall back for additional "languages"

   - [X] Need halcyon.scm parser
     + Need utilities to read hall records (e.g. halref, file parser)
      
   - [X] Implement halcyon file scanner:
     - scan current directory for halcyon.scm
     - if not found, (chgdir "../")
     - try again, until error (or pwd "/")?
     - -> error out

   - define operations:
     - [X] hall init : create new hall project
       - [X] hall init --here : create halcyon file here, & standard files.
       - [X] hall init --refresh : scan & regenerate guix.scm, HACKING, COPYING.
     - [X] hall scan : derive new halcyon file from project
       - [X] hall scan: … Basic re-generation.
     - [X] hall clean : remove all files not in specification.
     - [X] hall guix : Guix tooling
       - [X] hall guix : … generate a local dev guix file
       - [X] hall guix --type=tarball|git : generate a guix recipe for
         tarball or git (hub) based distribution
         - tarball dist : recipe for guix assuming no hall dependency
         - git dist : depends on gnu build infrastructure & hall
     - [-] hall dist : generate distribution tarball
       - [ ] hall dist : generate a tarball, and tidy project
       - [X] hall dist --infrastructure : only generate autotools
         infrastructure files
         + this will be part of the guix building process with "guile
           build system" (i.e. when building from a hall project
           (e.g. from git checkout or other source)).

   - [X] define cli
     - [X] hall
     - [X] hall init
     - [X] hall clean
     - [X] hall scan
     - [X] hall guix
     - [X] hall dist

   - [X] Develop build system & prepare for release
     - [X] Bootstrap build system from ourselves
     - [X] Consider & maybe rename project to halcyon or hall ->
       renamed to Hall
     - [X] Write basic documentation
       + Not info (for next release)
       + Instead, README file & demo screencasts
     - [X] Use settings in home for basic configuration
     - [X] Implement online gpl license fetching

   - [X] bugfixes:
     + [X] .dirstamp file needs to be handled
       * reproducible: run distcheck, then run hall clean

** Anatomy of a Guile Project

   - Documentation:
     - project/
       - README
       - HACKING
       - COPYING
       - guix.scm
       - docs/
         - project.texi
       - project/
         - foo.scm
         - bar.scm
         - frob.scm.in
       - tests/
         - foo.scm
         - baz.scm
       - project.scm
       - scripts/
         - project.in
         - project-too.scm

** `hall` Spec

   `hall` needs to be able to create a project from a spec.  The spec
   needs to include the following bits of information:
   - name
   - version
   - author [v2: plural & overrideable per file]
   - copyright [v2: overrideable per file]
   - synopsis
   - description
   - home-page
   - license
   - inputs (as guix variables)
   - files
     - libraries
     - tests
     - programs
     - documentation
     - infrastructure

** Defaults

   `hall` uses:
   - %base-libraries:
     + `(,(directory "$project" '()))
   - %base-programs:
     + `(,(directory "bin" `(,(scheme-file "$project"))))
   - %base-documentation:
     + `(,(readme-file) ,(hacking-file) ,(license-file license)
         ,(directory "doc" `(,(manual-file metadata))))
   - %base-tests:
     + `(,(directory "tests" '()))
   - %base-infrastructure:
     + `(,(guix-file metadata)
         ,(hall-file metadata))
    
   - In addition, for generating the guix.scm file we default to:
     - name: guile-$project
     - gnu-build-system
     - (native-inputs
          `(("autoconf" ,autoconf)
            ("automake" ,automake)
            ("pkg-config" ,pkg-config)
            ("texinfo" ,texinfo)
            ("guile-hall" ,guile-hall)))
     - (inputs `(("guile" ,guile-2.2)))
     - (arguments
          '(#:phases (modify-phases %standard-phases
                       (add-before 'configure 'set-guilesitedir
                                   (lambda _
                                     (substitute* "Makefile.in"
                                       (("^guilesitedir =.*$")
                                        "guilesitedir = \
 $(datadir)/guile/site/$(GUILE_EFFECTIVE_VERSION)\n"))
                               #t))
                       (add-after 'unpack 'hall-dist
                                  (lambda _
                                    (zero? (system* "hall" "dist"))))
                       (add-after 'hall-dist 'autoreconf
                                  (lambda _
                                    (zero? (system* "autoreconf" "-vif")))))))

** Files & Directories

   - files are procedures that return a procedure of two argument,
     expected to be the metadata & the filesystem context, which when
     invoked generates a file in the current filesystem context
     according to the file's spec.
     + the file's spec is as follows:
       + name
       + language
       + extension
       + contents

   - directories are procedures that return a procedure of one
     argument, expected to be the metadata & the filesystem context,
     which when invoked generates a directory in the current filesystem
     context according to the directory's spec.
     + A directory's spec is as follows:
       + name

   - metadata is an association list of the following fields from the spec:
     + name version author copyright synopsis description home-page
       license inputs

   - the current filesystem context is a list in which the first
     element is the path to the project root (in the case of an
     existing project), or the folder which will contain the project,
     and each element afterwards is the name of the next part of the
     directory structure of the project, e.g.:
     + '("/path/to/project" "doc")
     + '("/path/to/project" "project" "parsers")
     + '("/path/to/src project doc")
