[WIP] Begin porting over blog

This commit is contained in:
Jeremy Dormitzer 2019-05-31 18:31:22 -04:00
parent b2016ffded
commit 99b0e1d6f0
24 changed files with 2323 additions and 2 deletions

View File

@ -0,0 +1,51 @@
#lang pollen
title{A DSL for Music}
;; TODO add author and date
section{Haskell School of Music}
I recently discovered Haskell School of Music. Its a book about algorithmic music, which is awesome because: a) Ive been obsessed with procedural generation for years and b) I like music as much as I like programming. So you can imagine my excitement when I discovered that someone had written a textbook combining my favorite areas of study.
Haskell School of Music is aimed at intermediate-level CS students, so it covers a lot of the basics of functional programming. It aims to be an introduction to the Haskell programming language while also thoroughly examining computer music. It starts simply by defining the data structures that represent music, and progresses to functional programming concepts, procedurally generating music, and doing signal processing and MIDI interfacing to actually play the songs.
I like Haskell, but I want to write music in Clojure. Why? First of all, because its the One True Language (its fine if you disagree with me your opinion is valid even if its objectively incorrect). But more importantly, Clojure excels as an environment for writing link[#:href "https://en.wikipedia.org/wiki/Domain-specific_language"]{domain-specific languages} (DSLs). And as it turns out, writing algorithmic music using a DSL is a major win. Not only are DSLs expressive enough to portray creative expression, but DSLs written in Lisps are inherently extensible whereas Haskells static typing adds barriers to extensibility. Theres also an excellent music synthesis library for Clojure, ◊link[#:href "https://overtone.github.io/"]{Overtone}, that I want to be able to take advantage of.
Before we can explore what a DSL for music would look like, we need to understand how HSoM represents music as data.
section{Music as data}
HSoM breaks music down into its component pieces. It represents music using Haskell data structures:
codeblock[#:lang "haskell"]{
type Octave = Int
data PitchClass = Cff | Cf | C | Dff -- ...etc, all the way to Bss
type Pitch = (PitchClass, Octave)
type Duration = Rational
data Primitive a = Note Duration a
| Rest Duration
data Control =
Tempo Rational
Transpose Int
-- ...a bunch more
data Music a =
Prim (Primitive a)
| Music a :+: Music a
| Music a :=: Music a
| Modify Control (Music a)
}
Many of these type declarations are straightfoward, but a couple bear further discussion. A code{PitchClass} is an link[#:href "https://wiki.haskell.org/Algebraic_data_type"]{algebraic data type} representing all of the pitches: C#, Ab, F, and so on. By pairing a pitch class with an octave, we get a ◊code{Pitch}, which represents a specific note (for instance, middle C would be ◊code{(C, 4)}. A ◊code{Primitive} is a basic music building block, either a note or a rest. Note that it is ◊link[#:href "https://wiki.haskell.org/Polymorphism"]{polymorphic}: this is so that we can define types like ◊code{Note Duration Pitch} but also types like ◊code{Note Duration (Pitch, Loudness)} so that we can attach additional data to a primitive if we need to. A control represents the concept of making a modification to some music by changing the tempo, transposing it, or otherwise changing the output while keeping the underlying notes the same.
The Music type is where things get really interesting. Its an algebraic data type representing the concept of music in general. In fact, its powerful enough to fully represent any piece of music, from Hozier to Bach. A Music value is one of four possible types: a Prim, which is either a note or a rest; a Modify, which takes another Music as an argument and modifies it in some way; the :+: infix constructor, which represents two separate Music values played sequentially; and the :=: infix constructor, which represents two separate Music values played simultaneously.
The Music type has some important properties. First, its polymorphic for the same reason that the Primitive type is. This allows us to attach any type of data we want to music primitives, letting us express any musical concept (volume, gain, you name it).
Second, three out of its four constructors are recursive they take other Music values as arguments. This is the key that makes the data model so powerful. It allows you to model arbitrary configurations of notes, e.g. Note 1/4 (C 4) :=: Note 1/4 (E 4) :=: Note 1/4 (G 4) is a C major triad, and that expression evaulates to a Music value that can itself be passed to Modify, :+:, or :=: to weave it into a larger piece of music.
The result is an extraordinarily concise definition that still manages to encompass all possible pieces of music. Using these data structures, we can describe any song we can imagine.
But as powerful as this data type is, I wouldnt call it a domain-specific language. The static type system makes it inflexible: how would you combine a Note 1/8 ((C 4) 8), representing a note with pitch and loudness, with a Note 1/8 (E 4), representing a note with just a pitch? Sure, you could write a function to convert from one to the other, but at that point youve lost elegance and flexibility.
Heres where Clojure comes in.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

1885
src/js/highlight/CHANGES.md Normal file

File diff suppressed because it is too large Load Diff

24
src/js/highlight/LICENSE Normal file
View File

@ -0,0 +1,24 @@
Copyright (c) 2006, Ivan Sagalaev
All rights reserved.
Redistribution and use in source and binary forms, with or without
modification, are permitted provided that the following conditions are met:
* Redistributions of source code must retain the above copyright
notice, this list of conditions and the following disclaimer.
* Redistributions in binary form must reproduce the above copyright
notice, this list of conditions and the following disclaimer in the
documentation and/or other materials provided with the distribution.
* Neither the name of highlight.js nor the names of its contributors
may be used to endorse or promote products derived from this software
without specific prior written permission.
THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND ANY
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
DISCLAIMED. IN NO EVENT SHALL THE REGENTS AND CONTRIBUTORS BE LIABLE FOR ANY
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.

188
src/js/highlight/README.md Normal file
View File

@ -0,0 +1,188 @@
# Highlight.js
[![Build Status](https://travis-ci.org/highlightjs/highlight.js.svg?branch=master)](https://travis-ci.org/highlightjs/highlight.js) [![Greenkeeper badge](https://badges.greenkeeper.io/highlightjs/highlight.js.svg)](https://greenkeeper.io/)
Highlight.js is a syntax highlighter written in JavaScript. It works in
the browser as well as on the server. It works with pretty much any
markup, doesnt depend on any framework, and has automatic language
detection.
## Getting Started
The bare minimum for using highlight.js on a web page is linking to the
library along with one of the styles and calling
[`initHighlightingOnLoad`][1]:
```html
<link rel="stylesheet" href="/path/to/styles/default.css">
<script src="/path/to/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
```
This will find and highlight code inside of `<pre><code>` tags; it tries
to detect the language automatically. If automatic detection doesnt
work for you, you can specify the language in the `class` attribute:
```html
<pre><code class="html">...</code></pre>
```
The list of supported language classes is available in the [class
reference][2]. Classes can also be prefixed with either `language-` or
`lang-`.
To make arbitrary text look like code, but without highlighting, use the
`plaintext` class:
```html
<pre><code class="plaintext">...</code></pre>
```
To disable highlighting altogether use the `nohighlight` class:
```html
<pre><code class="nohighlight">...</code></pre>
```
## Custom Initialization
When you need a bit more control over the initialization of
highlight.js, you can use the [`highlightBlock`][3] and [`configure`][4]
functions. This allows you to control *what* to highlight and *when*.
Heres an equivalent way to calling [`initHighlightingOnLoad`][1] using
vanilla JS:
```js
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightBlock(block);
});
});
```
You can use any tags instead of `<pre><code>` to mark up your code. If
you don't use a container that preserves line breaks you will need to
configure highlight.js to use the `<br>` tag:
```js
hljs.configure({useBR: true});
document.querySelectorAll('div.code').forEach((block) => {
hljs.highlightBlock(block);
});
```
For other options refer to the documentation for [`configure`][4].
## Web Workers
You can run highlighting inside a web worker to avoid freezing the browser
window while dealing with very big chunks of code.
In your main script:
```js
addEventListener('load', () => {
const code = document.querySelector('#code');
const worker = new Worker('worker.js');
worker.onmessage = (event) => { code.innerHTML = event.data; }
worker.postMessage(code.textContent);
});
```
In worker.js:
```js
onmessage = (event) => {
importScripts('<path>/highlight.pack.js');
const result = self.hljs.highlightAuto(event.data);
postMessage(result.value);
};
```
## Getting the Library
You can get highlight.js as a hosted, or custom-build, browser script or
as a server module. Right out of the box the browser script supports
both AMD and CommonJS, so if you wish you can use RequireJS or
Browserify without having to build from source. The server module also
works perfectly fine with Browserify, but there is the option to use a
build specific to browsers rather than something meant for a server.
Head over to the [download page][5] for all the options.
**Don't link to GitHub directly.** The library is not supposed to work straight
from the source, it requires building. If none of the pre-packaged options
work for you refer to the [building documentation][6].
**The CDN-hosted package doesn't have all the languages.** Otherwise it'd be
too big. If you don't see the language you need in the ["Common" section][5],
it can be added manually:
```html
<script
charset="UTF-8"
src="https://cdnjs.cloudflare.com/ajax/libs/highlight.js/9.12.0/languages/go.min.js"></script>
```
**On Almond.** You need to use the optimizer to give the module a name. For
example:
```bash
r.js -o name=hljs paths.hljs=/path/to/highlight out=highlight.js
```
### CommonJS
You can import Highlight.js as a CommonJS-module:
```bash
npm install highlight.js --save
```
In your application:
```js
import hljs from 'highlight.js';
```
The default import imports all languages! Therefore it is likely to be more efficient to import only the library and the languages you need:
```js
import hljs from 'highlight.js/lib/highlight';
import javascript from 'highlight.js/lib/languages/javascript';
hljs.registerLanguage('javascript', javascript);
```
To set the syntax highlighting style, if your build tool processes CSS from your JavaScript entry point, you can import the stylesheet directly into your CommonJS-module:
```js
import hljs from 'highlight.js/lib/highlight';
import 'highlight.js/styles/github.css';
```
## License
Highlight.js is released under the BSD License. See [LICENSE][7] file
for details.
## Links
The official site for the library is at <https://highlightjs.org/>.
Further in-depth documentation for the API and other topics is at
<http://highlightjs.readthedocs.io/>.
Authors and contributors are listed in the [AUTHORS.en.txt][8] file.
[1]: http://highlightjs.readthedocs.io/en/latest/api.html#inithighlightingonload
[2]: http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html
[3]: http://highlightjs.readthedocs.io/en/latest/api.html#highlightblock-block
[4]: http://highlightjs.readthedocs.io/en/latest/api.html#configure-options
[5]: https://highlightjs.org/download/
[6]: http://highlightjs.readthedocs.io/en/latest/building-testing.html
[7]: https://github.com/highlightjs/highlight.js/blob/master/LICENSE
[8]: https://github.com/highlightjs/highlight.js/blob/master/AUTHORS.en.txt

View File

@ -0,0 +1,142 @@
# Highlight.js
Highlight.js — это инструмент для подсветки синтаксиса, написанный на JavaScript. Он работает
и в браузере, и на сервере. Он работает с практически любой HTML разметкой, не
зависит от каких-либо фреймворков и умеет автоматически определять язык.
## Начало работы
Минимум, что нужно сделать для использования highlight.js на веб-странице — это
подключить библиотеку, CSS-стили и вызывать [`initHighlightingOnLoad`][1]:
```html
<link rel="stylesheet" href="/path/to/styles/default.css">
<script src="/path/to/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
```
Библиотека найдёт и раскрасит код внутри тегов `<pre><code>`, попытавшись
автоматически определить язык. Когда автоопределение не срабатывает, можно явно
указать язык в атрибуте class:
```html
<pre><code class="html">...</code></pre>
```
Список поддерживаемых классов языков доступен в [справочнике по классам][2].
Класс также можно предварить префиксами `language-` или `lang-`.
Чтобы отключить подсветку для какого-то блока, используйте класс `nohighlight`:
```html
<pre><code class="nohighlight">...</code></pre>
```
## Инициализация вручную
Чтобы иметь чуть больше контроля за инициализацией подсветки, вы можете
использовать функции [`highlightBlock`][3] и [`configure`][4]. Таким образом
можно управлять тем, *что* и *когда* подсвечивать.
Вот пример инициализации, эквивалентной вызову [`initHighlightingOnLoad`][1], но
с использованием `document.addEventListener`:
```js
document.addEventListener('DOMContentLoaded', (event) => {
document.querySelectorAll('pre code').forEach((block) => {
hljs.highlightBlock(block);
});
});
```
Вы можете использовать любые теги разметки вместо `<pre><code>`. Если
используете контейнер, не сохраняющий переводы строк, вам нужно сказать
highlight.js использовать для них тег `<br>`:
```js
hljs.configure({useBR: true});
document.querySelectorAll('div.code').forEach((block) => {
hljs.highlightBlock(block);
});
```
Другие опции можно найти в документации функции [`configure`][4].
## Web Workers
Подсветку можно запустить внутри web worker'а, чтобы окно
браузера не подтормаживало при работе с большими кусками кода.
В основном скрипте:
```js
addEventListener('load', () => {
const code = document.querySelector('#code');
const worker = new Worker('worker.js');
worker.onmessage = (event) => { code.innerHTML = event.data; }
worker.postMessage(code.textContent);
});
```
В worker.js:
```js
onmessage = (event) => {
importScripts('<path>/highlight.pack.js');
const result = self.hljs.highlightAuto(event.data);
postMessage(result.value);
};
```
## Установка библиотеки
Highlight.js можно использовать в браузере прямо с CDN хостинга или скачать
индивидуальную сборку, а также установив модуль на сервере. На
[странице загрузки][5] подробно описаны все варианты.
**Не подключайте GitHub напрямую.** Библиотека не предназначена для
использования в виде исходного кода, а требует отдельной сборки. Если вам не
подходит ни один из готовых вариантов, читайте [документацию по сборке][6].
**Файл на CDN содержит не все языки.** Иначе он будет слишком большого размера.
Если нужного вам языка нет в [категории "Common"][5], можно дообавить его
вручную:
```html
<script src="//cdnjs.cloudflare.com/ajax/libs/highlight.js/9.4.0/languages/go.min.js"></script>
```
**Про Almond.** Нужно задать имя модуля в оптимизаторе, например:
```
r.js -o name=hljs paths.hljs=/path/to/highlight out=highlight.js
```
## Лицензия
Highlight.js распространяется под лицензией BSD. Подробнее читайте файл
[LICENSE][7].
## Ссылки
Официальный сайт билиотеки расположен по адресу <https://highlightjs.org/>.
Более подробная документация по API и другим темам расположена на
<http://highlightjs.readthedocs.io/>.
Авторы и контрибьюторы перечислены в файле [AUTHORS.ru.txt][8] file.
[1]: http://highlightjs.readthedocs.io/en/latest/api.html#inithighlightingonload
[2]: http://highlightjs.readthedocs.io/en/latest/css-classes-reference.html
[3]: http://highlightjs.readthedocs.io/en/latest/api.html#highlightblock-block
[4]: http://highlightjs.readthedocs.io/en/latest/api.html#configure-options
[5]: https://highlightjs.org/download/
[6]: http://highlightjs.readthedocs.io/en/latest/building-testing.html
[7]: https://github.com/highlightjs/highlight.js/blob/master/LICENSE
[8]: https://github.com/highlightjs/highlight.js/blob/master/AUTHORS.ru.txt

File diff suppressed because one or more lines are too long

Binary file not shown.

After

Width:  |  Height:  |  Size: 18 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 486 B

View File

@ -16,6 +16,11 @@
(lambda (kws kw-args . elements)
(txexpr 'h1 (zip-kws kws kw-args) elements))))
(define section
(make-keyword-procedure
(lambda (kws kw-args . elements)
(txexpr 'h2 (zip-kws kws kw-args) elements))))
(define link
(make-keyword-procedure
(lambda (kws kw-args . elements)
@ -25,3 +30,13 @@
(make-keyword-procedure
(lambda (kws kw-args . elements)
(txexpr 'img (zip-kws kws kw-args) elements))))
(define codeblock
(make-keyword-procedure
(lambda (kws kw-args . elements)
(let ((new-kws (map (lambda (kw)
(if (eq? kw '#:lang) '#:class kw))
kws)))
(txexpr
'pre empty
(list (txexpr 'code (zip-kws new-kws kw-args) elements)))))))

View File

@ -2,6 +2,7 @@
(define navbar-height 60)
(define serif-font-stack "'Century Supra', 'Palatino Linotype', Palatino, Palladio, 'URW Palladio L', 'Book Antiqua', Baskerville, 'Bookman Old Style', 'Bitstream Charter', 'Nimbus Roman No9 L', Garamond, 'Apple Garamond', 'ITC Garamond Narrow', 'New Century Schoolbook', 'Century Schoolbook', 'Century Schoolbook L', Georgia, serif")
(define monospace-font-stack "'Triplicate Code', SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace")
(define body-color "#404040")
(define link-color "royalblue")
(define link-hover-color "midnightblue")
@ -44,6 +45,15 @@ a:hover {
color: |link-hover-color|;
}
code, pre {
font-family: |monospace-font-stack|;
font-size: 20px;
}
pre > code.hljs {
padding: 1.5em;
}
.main {
display: grid;
grid-template-columns: repeat(12, 1fr);

View File

@ -2,8 +2,10 @@
<head>
<meta charset="utf-8">
<title>(or (select 'h1 doc) "Jeremy Dormitzer")</title>
<link rel="stylesheet" type="text/css" href="fonts/century-supra/stylesheet.css" />
<link rel="stylesheet" type="text/css" href="stylesheet.css" />
<link rel="stylesheet" type="text/css" href="/js/highlight/styles/default.css" />
<link rel="stylesheet" type="text/css" href="/fonts/century-supra/stylesheet.css" />
<link rel="stylesheet" type="text/css" href="/fonts/triplicate/stylesheet.css" />
<link rel="stylesheet" type="text/css" href="/stylesheet.css" />
</head>
<body>
<div class="main">
@ -12,5 +14,7 @@
<footer>
© Jeremy Dormitzer 2019
</footer>
<script src="/js/highlight/highlight.pack.js"></script>
<script>hljs.initHighlightingOnLoad();</script>
</body>
</html>