284174d375 | ||
---|---|---|
.gitignore | ||
CHANGELOG.org | ||
README.org | ||
UNLICENSE | ||
mkly | ||
mkly-tests.scm |
README.org
mkly
README
Features
- Provides a default set of rules, so you don't have to.
- Provides a full-blown programming language for writing rules.
- Tiny (< 150 lines); trivial to hack on.
- Implemented and configured using the only reasonable language (a Lisp 😏)
Non-goals
- Incremental builds
Installation
Guile must be available at /usr/bin/guile
- Place
mkly
in your $PATH or your project root -
Make it executable -
chmod u+x mkly
-
In your project root, run -
./mkly
Invocation and default rules
mkly
can be run without arguments -
mkly
This will compile main.ly
and part-*.ly
.
You can pass one or more targets -
mkly <target>*
Each target will be checked against the patterns defined in the rules, and the actions for all matching patterns will be run.
The default targets are
main.ly
- compiles the file without point-and-click. Emits a file tooutput/<project-name>
.- a file name matching
part-*.ly
, e.g.part-foo.ly
- compiles the file without point-and-click. Emits a file tooutput/<project-name>-part-foo
. dev
- compilesmain.ly
with point-and-click enabled. Emits a file tooutput/<project-name>-pacON
.all
- compilesmain.ly
and allpart-*.ly
files, without point-and-click.
If a subdirectory is supplied, mkly
will descend to it for all following targets (until another subdirectory on the command line is encountered) -
mkly main foo/ dev bar/ main dev
Here, target "main" will be run in the project root, target "dev" will be run in the subdirectory "foo/", and target "main" and "dev" will be run in subdirectory "bar/".
Defining rules
Rules are returned as a list by the procedure rules
. This procedure can be redefined by loading your own Scheme file, by running mkly
with the --load
/ -l
command line option.
Some default variables are defined for use in defining rules -
project-root
- the project root directoryproject-name
- by default, the basename of the parent directoryshell-path
- path to the shell you want to use for running your commands
Built-in helper functions
(use-dir! DIR)
- creates DIR if it does not exist. DIR must be a string. Raises an error if DIR exists and is not a directory. Returns DIR.(vcs-current-branch)
(parent PATH)
- returns the parent directory component of PATH, or #f if none is present.(getcwd-base)
- returns the basename of the current directory.
TODO
Certain [50%]
- Make it declarative - define options and their effect, and the structure of the command, separately from the code that makes it happen.
- Use regexps to define target names and how the output file name(s) derive from them.
- Name files differently if PAC is on - the upside of this is, you don't accidentally send someone the point-and-click-enabled version of the file. The downside is, it's easy to have file-pacON.pdf open during editing, while the script is actually compiling to file.pdf (or vice-versa) 1, and wonder why your score isn't updating.
- Create output directory if it doesn't exist!
-
Remove duplicate layer of CLI options - currently there's a needless extra layer of CLI options for options which already exist. Should make code simpler, UI familiar.
-
But the Lilypond CLI is ugly - what's better, "pac=off", or "-dno-point-and-click"? :\
- After the revamp, the script doesn't (yet) aim to want to support options like this; the idea is that the user specifies a situation as a target, and all options relevant to that situation are passed (as specified in the rules by the user). It's a "maybe" to-do.
-
- Tab completion of specified target names
- Multiple targets in one command e.g. to compile both the main score and the parts in one command.
-
Targets containing other targets.
- I've tried calling the script itself with the required targets - not sure if that actually works. Especially considering that #7 - multiple targets in one command - isn't implemented yet.
- If
mkly
is not in the user's $PATH and is invoked as./mkly
, the shell won't be able to find it if it calls itself. We can try constructing the path to the script (usinggetcwd
- if(first (command-line))
is "./mkly", it's in the current working directory)
-
Shell globs, both in targets and in actions.
- Document shell-path as a user variable
- Use shell-path to run commands
-
Sub-project operations
-
Specify targets for sub*-project(s), instead of project in current working directory.
- The current way is somewhat inelegant, though - you either modify all rules to also work in sub-projects, or you make new rules for sub-projects…why can't the same rule work for both? What if we could specify a subdirectory, followed by the usual targets, resulting in us
cd
ing into that directory and running the usual targets? Same rules working in both situations!
- The current way is somewhat inelegant, though - you either modify all rules to also work in sub-projects, or you make new rules for sub-projects…why can't the same rule work for both? What if we could specify a subdirectory, followed by the usual targets, resulting in us
- Use sub-project-specific mkly-rules.scm if present, else use project-root mkly-rules.scm
- I want to compile a particular target in every subproject. (use globs)
(Old) implementation notes
-
Maybe…if the input file in a target entry is just a "/" (or maybe "->"?), the target name will be understood as being the target to run in either
- all subdirectories directly below the directory containing the current build.scm (in this case, it is an error if any of these subdirectories do not contain a build.scm)
- all subdirectories in which a build.scm can be found, directly below the directory containg the current build.scm
-
- Expand branch detection to include more VCSs.
- Add -h/–help, and -d/–debug or -v/–verbose
- Warn users about ignored
mkly-rules.scm
, if detected - Add command line option to load a Scheme file, serving as an extension point (e.g. to define custom rules)
Maybe [0%]
- Allow users to define (command-line) options and their effect.
-
VCS branch integration - check what branch you're on. If it's branch X (e.g. "main"), do nothing. If it's something else, add the name to the output file.
- Or to the output directory name, e.g. files from the main branch go to "output/", files from branch "foo" go to "output-foo/", etc.
- Default rules for orchestral projects - for target
part-<instrument>.ly
, compile<instrument class>/<instrument>.ly
- Make
rules
into a macro -
Implement Scheme expressions as an action.
- one possible way - all actions are Scheme expressions - for shell commands, create a
($ ...)
form (with$
doing whatrun
does now) which iseval
-uated if it matches a target. (see branch "$-syntax")
- one possible way - all actions are Scheme expressions - for shell commands, create a
-
Replace regexp patterns with glob patterns?
- more consistent (since targets and actions use globs too), but possibly less powerful.
Bugs
- Barfs when placed in and run from directories with a path containing non-ASCII characters. This is a Guile bug.
-
./mkly
->sh: 1: main.ly: not found
- Default rule (no pattern provided) and
else
seem to conflict - do we want to do different things when there's no pattern provided and when a provided pattern does not match, or the same thing? - Meta-targets - if the command does not match another rule, run as shell command; otherwise treat as list of targets
- Default rule (no pattern provided) and
- chdir to project root before descending into subdir
- Error on unmatched pattern
License
I dream of a world where all software is liberated - transparent, trustable, and accessible for anyone to use or improve. But I don't want to make demands or threats (e.g. via legal conditions) to get there.
I'd rather make a request - please do everything you can to help that dream come true. Please Unlicense as much software as you can.
These are likely to happen if you have a compile-with-last-command-on-save setup, like in my Emacs.