text:
***Caveat*** Please note that the bulk of this tutorial was written in [September 2015](https://groups.google.com/forum/#!topic/pollenpub/H-vl05Tjixs), before Pollen reached version 1.0. Now, as of December 2019, Pollen has reached version 2.1, and Andres Moreno was kind enough to update everything to work with Pollen 2! ***End caveat***

# A poor guide to Pollen
The [official Pollen documentation](pkg-build.racket-lang.org/doc/pollen/) is a rich and hearty repast. That may be why it took me longer than expected to get where I wanted to go.

So, here’s a poor and meagre introduction that may help others get started as quickly as possible.

## Goal
I’m trying to write Pollen markup that generates Dave Liepmann’s [Tufte CSS](http://www.daveliepmann.com/tufte-css/)-compliant HTML. Tufte CSS has some nice rules for sidenotes and headings that I’d like to write for, without writing HTML.

## Preliminaries
Install [Racket](http://download.racket-lang.org/), either by downloading an installer from there, or using your operating system's package manager. Pollen also includes detailed [Installation](https://docs.racket-lang.org/pollen/Installation.html) instructions for Windows, Mac, and Linux.

> On **macOS**, if you use [Homebrew](https://brew.sh/), simply run `$ brew install minimal-racket`!

Then install Pollen by running `$ raco pkg install pollen` and answering “yes” a couple of times.

Now. After reading portions of [three](http://pkg-build.racket-lang.org/doc/pollen/first-tutorial.html) [longform](http://pkg-build.racket-lang.org/doc/pollen/second-tutorial.html) [tutorials](http://pkg-build.racket-lang.org/doc/pollen/third-tutorial.html) ([fourth](http://pkg-build.racket-lang.org/doc/pollen/fourth-tutorial.html) available), a [mini-tutorial](http://pkg-build.racket-lang.org/doc/pollen/mini-tutorial.html), and a [quick tour](http://pkg-build.racket-lang.org/doc/pollen/quick-tour.html), you will likely be very excited about many things. But for purposes of this poor guide, you can forget everything about DrRacket, `.pp` Pollen preprocessor files, `.pmd` & Pollen-Markdown mode, the Pollen project server (`raco pollen start`), etc.

We’ll be writing Pollen markup directly in `.html.pm` files, rendering them from the command line with `raco pollen render`, and viewing just the result in a browser. Clone this repository and follow along.

**N.B.** I’m assuming some passing familiarity with a Lisp, like Common Lisp or Emacs Lisp or Scheme or Clojure. The examples that follow have enough weird Pollen awesomeness that I can’t stop and explain parens or symbols or [`,@ unquote-splicing`](http://docs.racket-lang.org/guide/qq.html). But I will try to point out Racketisms to save some Googling, and it’s always a good idea to [Learn X=Racket in Y Minutes](http://learnxinyminutes.com/docs/racket/).

## Take One. Basic and not-so-basic functionality.
In the `take1/` directory there are
- two input files: Pollen markup in `take1.html.pm` and an HTML template `template.html`,
- one helper file: the `tufte.css` file from Liepmann, and
- out output file: `take1.html` which is generated by running `raco pollen render take1.html`.

The reason you could forget about Markdown and the Pollen preprocessor is because these are small fry compared to real Pollen markup. Compare the Pollen markup input and its rendered output:

<img width="1482" alt="take1-screenshot" src="https://cloud.githubusercontent.com/assets/37649/9675781/2c032492-5290-11e5-9a88-68aacc828ab3.png">

In the Pollen markup file `take1/take1.html.pm`, we have some Racket function definitions starting with ◊, then a bunch of content. Wait, maybe I overstated the difference between Racket code versus content, because what’s the difference between
- ``◊(define (emphatic . xs) `(em ,@xs))``, and
- ``◊emphatic{italicize things}``? Or, worse,
- ``◊h1{Take One. Or, Let’s Try To Get the Basics.}``?

### Pollen text mode versus Racket mode: Pollen’s two syntaxes for calling functions
Here’s the first thing you need to know. There’s a **one-to-one equivalence** between
- `◊foo[arg1 arg2]{final-arg}`, which [is called](http://pkg-build.racket-lang.org/doc/pollen/reader.html#%28part._.The_two_command_modes__text_mode___.Racket_mode%29) Pollen text mode, and
- `◊(foo arg1 arg2 final-arg)` which is Racket mode.

Both call a Racket function `foo`. This isomorphism allows you to treat `foo` as a plain Racket function using the latter, and as convenient syntactic sugar to define arbitrary X-exprs with the former—X-exprs which may resolve to HTML tags. Because…

### Pollen forgives undefined functions
The other thing you need to know is also awesome: **if Pollen finds you using functions-tags that you haven’t `define`d, it’ll treat them as plain HTML tags**. This is why `take1.html.pm` can call `◊h1{Take One …}` without anybody defining `h1` anywhere.

Put the two of these factoids together and you see why we can use `◊span` as
- a Pollen tag via `◊span['((class "hidden") (id "id1"))]{my span}`,
- **and** as a Racket function via `◊(span '((class "hidden") (id "id2")) "my other span")`, without explicitly defining `span`.

Of course you can see that, while they’re equivalent, in practice it’s easier to use one syntax in for some situations and the other for others, if only because you don’t need to quote text when you use `◊span{look ma, no quotes!}`.

### Explaining aforementioned usages
Now you can understand those three lines of code above.

``◊(define (emphatic . xs) `(em ,@xs))`` is written using Racket mode syntax, and defines a function called `emphatic` with all arguments rolled into a list called `xs` (just like `def foo(*args)` in Python or `varargin` in other languages), and which returns the input arguments list `xs` prepended with the symbol `em` using a bit of that [quasiquote](http://docs.racket-lang.org/guide/qq.html) magic the Lisp family is famed for.

We invoke this function using `◊emphatic{italicized text}`, and it renders as `<em>italicized text</em>`.

And as Pollen smartly passes through undefined functions as tags, ``◊h1{Take One. Or, Let’s Try To Get the Basics.}`` produces the appropriate `<h1>` tag.

Test your understanding: given this `linky` function,
```racket
◊(define (linky url . xs) `(a ((href ,url)) ,@xs))
```
what would
```racket
◊linky["http://github.com"]{slinky dress}
```
render as? You may need to refer to the documentation on [`unquote`](http://docs.racket-lang.org/guide/qq.html) again. Note how this sophomoric implementation prevents `linky` from being given additional attributes like `id` or `class`.

### Templates: packaging it into a tidy HTML file
So in the `take1/` directory, run
```
$ raco pollen render take1.html
```
Unlike other markup translators I’ve used, Pollen doesn’t write to stdout, and will overwrite `take1.html`. For now it can just be opened it in a browser (we’ll talk about webservers in a subsequent take).

You may have noticed, even in the screenshot above, that there is some boilerplate in the rendered HTML that’s not in the origial Pollen markup, like `head` and `meta` tags. This comes from a template file, in our case called `take1/template.html`.

This template is also a Pollen file, despite lacking any Pollen-esque file extension. Note a couple of ◊s in it: the first one is just a bit of showing off—the contents of the first `<h1>` tag is grabbed via a Pollen function `select` and used to set the page’s `<title>`: `<title>◊select['h1 doc]</title>`. (In Racket mode, this would be `◊(select 'h1 doc)`.) The X-expr `doc` containing the abstract syntax tree (AST) of `take1.html.pm` is available when the template is rendered, which `select` can scan, à la `getElementsByTagName`.

A bit later, inside a Tufte CSS-specific `<article>` tag, another Pollen function `->html` converts the AST to HTML. `->html` is clearly tightly intertwined with its target format. For contrast, here's an alternative AST-to-*plaintext* converter:
```racket
◊(apply string-append (filter string? (flatten doc))) ; instead of (->html doc). Generates plaintext.
```
After flattening the nested lists and throwing away tags and attributes, concatenate the strings that remain and you have a pretty good plaintext representation of `take1.html.pm`.

### Summary of Take One

The functionality demonstrated so far is pretty elementary. The Pollen syntax can seem peculiar, and one couldn’t be blamed for being uneasy with the thought of constantly dropping into Racket. Maybe worst of all is we don’t have any easy way to *italicize* text like Markdown.

But I am already awestruck by the vistas of flexibility Pollen’s approach reveals. Having your document and your template be fully-programmable in the same language dramatically lowers the activation energy for complex document workflows.

The classic gripe of technical writers with Markdown—its lack of footnotes—can readily be fixed by a couple of quick Racket functions: you could write your paper in Markdown, use Pollen annotations just for the footnotes, and output another Markdown file with footnotes all fancy. But I’d argue that Markdown offers precious little besides single-character markup compared to Pollen markup, hence my advice to throw oneself whole-heartedly on Pollen markup.

In the next take, we’ll see how to make Tufte CSS sidenotes and get proper paragraph tags, two much more cognitively burdensome tasks.

## Take Two. Things are harder than they appear.

Now consider the contents of the `take2/` directory. Again we have a Pollen markup file, a template, the Tufte CSS `.css` file, and the rendered HTML. Re-render the last with
```
$ raco pollen render take2.html
```

### Sidenote sausage
As mentioned above, [Tufte CSS](http://www.daveliepmann.com/tufte-css/) has nice sidenotes. But a sidenote isn’t a single tag. Here’s how the sidenote sausage is made:
```html
Flowing text.
<label for="LABEL" class="margin-toggle sidenote-number"></label>
<input id="LABEL" class="margin-toggle" type="checkbox"></input>
<span class="sidenote">SIDENOTE CONTENT</span>
More flowing text.
```
We’d like to get this from just
```
Flowing text.◊sidenote["LABEL"]{SIDENOTE CONTENT} More flowing text.
```
The Pollen magic from the first take doesn’t help here. At best we could squeeze all three of these tags into a single `<sidenote>` tag, which browsers could probably handle just fine. But can we find something more elegant, to just place three adjacent tags in the flow of the parent tag?

Matthew Butterick’s [source code](http://unitscale.com/mb/technique/pollen.rkt.html) to [Making a dual typed / untyped Racket library](http://unitscale.com/mb/technique/dual-typed-untyped-library.html) shows us how to do this. It defines a `splice` Racket function and includes a test for it, and here’s my version of it:
```racket
(define (splice xs)
  (apply append (for/list ([x (in-list xs)])
                  (if (and (txexpr? x) (member (get-tag x) '(splice-me)))
                      (get-elements x)
                      (list x)))))

(splice '(p "foo" (splice-me "bar") "zam")) ; should be equal to '(p "foo" "bar" "zam")
```
All this is worth puzzling over for a bit. As I make it out, `splice` searches the contents of an X-expr (which is a list, and without recursing into any nested sublist child-tags), looking for a child tag called `splice-me`. When it finds one, it replaces the child tag with its contents. So an input representing `<p>foo <splice-me>bar</splice-me> zam</p>` becomes `<p>foo bar zam</p>`. That `txexpr` and `get-tag` stuff is for dealing with the specifics of X-exprs (which *are* lists, i.e., S-exprs, but with extra pixie dust on top).

So if instead of enclosing the `label`, `input`, and `span` tags inside a `<sidenote>` tag like I bemoaned doing a minute ago, enclose them in a `<splice-me>` tag, and ask Racket to run `splice` on every sub-X-expr in the document.

Pollen has a neat way of doing this. It’s related to something I forgot to point out about the rendered HTML in Take One, that Pollen markup is enclosed in a `<root>` tag by Pollen convention. So define a `root` Racket function:
```racket
(define (root . xs)
  (decode `(decoded-root ,@xs) #:txexpr-elements-proc splice))
```
[`decode`](http://pkg-build.racket-lang.org/doc/pollen/Decode.html) looks like a pretty powerful function that can operate on X-exprs—any X-exprs, including subsets of the `doc` AST (and the `#:` syntax is Racket for keyword arguments). Here, `decode` is used to apply `splice` to every child node of `<root>`, that is, the entire document, and put the results in a new tag, `<decoded-root>`.

So now, instead of the contents of the Pollen markup going in a `<root>` tag, they’ll be in `<decoded-root>`. Any `<splice-me>` tag will have its contents spliced into its parent tag.

Sidenote sausage cooked.

You are appalled that one had to write so much Racket to do something that one would think was a pretty common task—replacing one tag with mutliple adjacent ones. Why does Pollen give us any simpler way to do this? But that’s the point of having a fully-programmable document. Unix doesn’t have a command line utility to do every task, but the Unix philosophy of small tools that do one thing well and can be chained means it doesn’t have to. C doesn’t give you hash tables or linked lists: it gives you the tools to write them yourself. XML doesn’t specify every conceivable semantic tag: it embraces extensibility. The discomfort felt at performing surgery on your document’s complete AST soon evaporates into relief—and perhaps joy—at being able to surgically modify your document’s AST.

### There are no newlines under the sun
One very nagging thing about the Pollen renders so far is that newlines are passed through, and that you immediately noticed when you looked at `take1.html` in a browser—it looked weird because it lacked `<p>` paragraph tags, and it was basically a single run-on paragraph.

Dealing with `<br>` and `<p>` tags, line breaks and paragraph tags, is thankfully something that you don’t have to write yourself, as Pollen comes with some [fancy functionality](http://pkg-build.racket-lang.org/doc/pollen/Decode.html#%28def._%28%28lib._pollen%2Fdecode..rkt%29._detect-paragraphs%29%29) to handle this. `detect-paragraphs` is pretty feature-rich, but to get the job done for `take2.html`, its default functionality is entirely sufficient.

It is similar to `splice`, discussed a second ago, in that it scans an X-expr without recursing and converts newlines to `<p>` and `<br>` tags appropriately. So like `splice`, we can ask `decode` to run `detect-paragraphs` on each sub-X-expr while it’s running `splice`. Here’s the expanded call to `root`:
```racket
◊(define (root . xs)
  (decode `(decoded-root ,@xs)
          #:txexpr-elements-proc (compose1 detect-paragraphs splice)
          #:exclude-tags '(pre)
          ))
```
Note that the `#:txexpr-elements-proc` keyword argument to `decode` must be a single function, not a list, but we happen to be using a functional programming language here. `(compose1 detect-paragraphs splice)` returns a single function that will apply `splice` first, then `detect-paragraphs`.

And what about that `#:exclude-tags` keyword argument? We don’t want to convert newlines in `<pre>` tags, and Pollen has thoughtfully given this high-level mechanism to prevent those from being decoded.

It may be a good exercise to figure out how to run `splice` on `pre` tags but not `detect-paragraphs`: `detect`’s high-level customizations might not be sufficient for this and one may have to write a couple of lines of Racket.

### Summary of Take Two

This take is titled "things that are harder than they appear", but having seen what it takes to splice a tag’s children into its parent, I completely appreciate how Racket’s power can make mincemeat out of complex tasks once one understands the underlying data structures—and how Pollen dramatically reduces the activation energy to whipping up some Racket code.

Then we saw that there are other things which Pollen has thought about and provides out-of-the-box solutions, like newline detection, smart punctuation (which I haven’t demonstrated here), etc. Yet even thees are steeped in the Racket ethos, and are hugely programmable.

In the next and last (planned) take, we’ll set up some infrastructure to make Pollen authoring even easier. We’ll set up a custom Nginx webserver that lets the HTML page auto-refresh whenever the Pollen markup is saved.

## Take Three, where we get all steampunk
***Nota bene*** Pollen now includes a [project webserver](https://docs.racket-lang.org/pollen/first-tutorial.html#%28part._.Using_the_project_server%29)! Please consider using that, you don't need this!

So far, my Pollen workflow has been edit–save–compile–refresh, switching between a text editor (gvim), command line, and browser. This is tiring and here’s how I chose to streamline this.

First, I install [Node.js](https://nodejs.org), a popular cross-platform JavaScript runtime with a very large ecosystem, and run a ~100-line JavaScript program which starts a webserver and watches a single Pollen markup file for changes. When I save that file, Node calls `raco` to re-render the HTML and sends a server-sent event to any browser viewing the rendered HTML, telling it to refresh the page.

The HTML page is aware of server-sent events because of some JavaScript we embed in it, and JavaScript is also how it refreshes itself when it gets the command to do so. This is very handy while authoring, but such infrastructure code should be removed before uploading to a public webserver for general viewing. So the last thing we’ll do is make our Pollen markup aware of our desire to make a testing versus production version of the output using an environment variable. Our `template.html`, which contains HTML boilerplate, will check for a `POLLEN` environment variable, and include refresh logic only when in testing mode, otherwise leaving it out. This is the only Pollen-specific part of this take and is a snap given how much we know about Pollen now.

**Aside** I personally use Nginx with this [HTTP push stream module](https://github.com/wandenberg/nginx-push-stream-module), because Nginx is far more performant than Node when it comes to serving big webpages loading images, JavaScript libraries, JSON datasets, MathJax, etc. There’s also a lot less custom code—none, really. But Nginx doesn’t work (well) on Windows, and one has to compile it from scratch to get the HTTP push stream module (which abstracts server-sent events, WebSockets, etc.). Rather than force readers of this poor guide to front this high NRE, I made this Node.js alternative. And I chose Node because of my own familiarity with it, and because it is cross-platform. It should possible to do all this in Racket.

### Setup and use

**Step 0** As a preliminary step, in the `take3/` directory, render the Pollen markup file:
```
$ POLLEN=TESTING raco pollen render take3.html
```
You could even read the input or output files, if you like. I note in passing that I’ve moved all Racket code out of the Pollen markup file into a `take3/pollen.rkt` Racket file, which Pollen loads as a module.

**Step 1** As a first step, download and install [Node.js](https://nodejs.org). Works on Mac, Linux, and Windows, ARM and x86, the lot.

**Step 2** Second, in the `take3/` directory in a terminal, run
```
$ npm install
```
`npm` is the package manager for Node. It looks at `take3/package.json` and installs a handful of dependencies in the `take3/node_modules` directory.

> **Step 2.5** If you are using Internet Explorer, Edge, Opera Mini, or any browser that doesn’t support EventServer (full list of unsupporting browsers at [Can I Use](http://caniuse.com/#feat=eventsource)), copy the `node_modules/event-source-polyfill/eventsource.min.js` shim to the `take3/public` folder:
```
cp node_modules/event-source-polyfill/eventsource.min.js public/
```

**Step 3** Third, run
```
$ node server.js take3.html.pm "POLLEN=TESTING raco pollen render take3.html"
```
This starts the Node application, including a webserver and a file watch on the `take3.html.pm` Pollen markup file. That string `"POLLEN=TESTING raco …"` is what will be executed when changes to `take3.html.pm` are detected.

**Step 4** Next, visit [http://localhost:3000/take3.html](http://localhost:3000/take3.html) to view the rendered HTML being served by the Express.js webserver in Node.

**Step 5** For my final trick, I position my browser so that I can see it and my text editor at the same time. I edit the `take3.html.pm` Pollen markup file and save it. In a second or three, the browser refreshes in same place, showing my changes.

***Hurrah!***

N.B. Fastidious readers may notice two browser refreshes for a single save. The [file watching API](https://nodejs.org/docs/latest/api/fs.html#fs_fs_watch_filename_options_listener) in Node (and anywhere else) is a little persnickety and may choose to detect two changes, one immediately after another, when the file changed only a single time.

### Rendering for production environments

I don’t want to get into the details of how server-sent events and their client-side counterpart, the EventSource API, are used here. The details are all in `take3/server.js` and in `take3/template.html`. Hopefully you can change the arguments to `node server.js` to work for different projects, without coding.

But do note that this auto-refresh trick works because of custom JavaScript embedded in `template.html`. We don’t want this code to be present when we publish a Pollen document for a production environment. It likely won’t cause any harm but really should be omitted if it’s not needed.

For this reason, `template.html` checks to see if a `POLLEN` environment variable is available. One can set this by prefixing the variable to raco command:  `POLLEN=TESTING raco …`. The template assumes that, if this environment varialbe is defined, Pollen is being run in a testing environment—it doesn’t care what the actual contents of the string are.

And if the template decides it is in a testing environment, it will include a couple of `<script>` tags in the HTML header which load the JavaScript that facilitates the auto-refresh feature. If no `POLLEN` environment variable is defined, these scripts are omitted.

This is classic Pollen:
```racket
◊(if (getenv "POLLEN") "
<script src='/public/eventsource.min.js'></script>
<!-- ... ... ... -->
" "")
```
We use Racket’s `if`, and choose to embed either a multi-line string containing HTML and JavaScript code, or an empty string. Happily, HTML and JavaScript can use single- and double-quotes just as easily, so I had to do no escaping of quotes in the `if` form! I can copy-and-paste HTML/JavaScript from non-Pollen sources without any problems. If I insisted on using double-quote, though, I would have had to escape them within the multiline quote.

When rendering for production, simply omit the `POLLEN=TESTING` environment variable and the resulting HTML file will not mention refresh events: simply run `$ raco pollen render take3.html` and upload the resulting file to your web host.

> **A technical note on `server.js`** The Node server sends browsers a message not only when it detects a file change, but also if it receives a POST request on `/events/ID` for some string `ID`—in this case, the Node server forwards the POST message to the browser. Therefore, one could have the server send a request to refresh via the following command in a terminal:
```
$ curl -f -s -X POST http://localhost:3000/events/refreshme -d 'change'
```
> Note how the ID of the event (or channel) is `refreshme` and the message is `change`, which is the same channel and message that the browsers are looking for. If instead of `-d 'change'` one had `-d 'hi'`, one would see `hi` in the browser JavaScript console. This provides another useful way to communicate from your shell to the browser. A script that combines Pollen rendering and POSTing a refresh request to the server (to forward to browsers) is included in the `take3/testing.sh` script.

### Summary of Take 3

In this last take of this poor guide to Pollen, we were able to use Racket’s multiline string support to effortlessly embed HTML and JavaScript in a document’s rendered output based on if/then logic.

But this take really focused on infrastructure to make the Pollen authoring process smoother. We cobbled together some JavaScript, script kiddie style, to watch a file for changes, rerun the Pollen renderer when changes were detected, and use server-sent events and the EventSource web technologies to communicate to the browser to refresh the page, getting the latest content.

## Epilogue

The first take of this poor guide revisited the basic features of Pollen that one needs to know to start being productive in it. The second looked in-depth into one situation where one needed a bit of common Racket to achieve some pedestrian results. The third and final take set up some infrastructure to auto-refresh a document in a browser when it was saved.

By the end of this guide, I hope you are comfortable writing Pollen documents and confident in Pollen’s ability to transform its markup into any HTML you want. And by extension, any other format too.

Using Pollen markup has been much more liberating than using Markdown with custom Pandoc writers written in Lua because, although Pandoc does give custom writers an AST, it is not as flexible as having the full X-exprs. Although it looks a bit more “pointy” than Markdown, I think the benefits of Pollen markup far make up for it.

repo_name: fasiha/pollen-guide

repo_language: HTML

mime_type: text/html


text:
/*

Installation: install Node.js from https://nodejs.org. Then run

$ npm install

to install dependencies locally (mainly Express and related middleware).

Usage:

$ node server take3.html.pm "POLLEN=TESTING raco pollen render take3.html"

Open http://localhost:3000/take3.html

Whenever take3.html.pm is saved, Node will detect it, rerun Pollen, and send a
message to the browser, triggering a refresh.

 */

"use strict";

var FILE_TO_WATCH = process.argv[2] || '';
var COMMAND_TO_RUN = process.argv[3] || '';
var PORT = process.argv[4] || 3000;

var fs = require('fs');
var child_process = require('child_process');
var EventEmitter = require('events');
var express = require('express');
var onFinished = require('on-finished');
var bodyParser = require("body-parser");

var events = {refreshme : new EventEmitter()};

var app = express();
app.use('/public', express.static('public'));
app.use(bodyParser.text({ type: '*/*' }));

app.get('/', function(req, res) { res.send('Hello World!'); });

app.get(/([a-zA-Z0-9_]+).html/, function(req, res) {
  var filename = req.params[0] + '.html';
  console.log('Sending file:', filename);
  fs.readFile(filename, {encoding : 'utf8'}, function(err, data) {
    if (err) {
      res.status(404).end();
    }
    res.send(data);
  });
});

app.post("/events/:id", function(req, res) {
  // This was helpful: http://www.html5rocks.com/en/tutorials/eventsource/basics/
  var id = req.params.id;
  if (!(id in events)) {
    events[id] = new EventEmitter();
  }
  events[id].emit('sendMessage', 'sendMessage', req.body || "empty");
  res.status(200).send('Thanks\n');
});

app.get("/events/:id", function(req, res) {
  console.log('Subscription received');
  var id = req.params.id;

  res.writeHead(200, {
    'Content-Type' : 'text/event-stream',
    'Cache-Control' : 'no-cache',
    'Connection' : 'keep-alive'
  });
  res.write("\n");

  // Adapted from
  // http://www.futureinsights.com/home/real-time-the-easy-way-with-eventsource-angularjs-and-nodejs.html
  function sendSse(eventname, data, id) {
    console.log('Event transmitted. Event:', eventname, 'data:', data, 'id:',
                id);
    res.write("event: " + eventname + "\n");
    if (id) {
      res.write("id: " + id + "\n");
    }
    res.write("data: " + JSON.stringify(data) + "\n\n");
  }
  if (!(id in events)) {
    events[id] = new EventEmitter();
  }
  events[id].on('sendMessage', sendSse);

  onFinished(res, function(err, res) {
    events[id].removeListener('sendMessage', sendSse);
  });

});

var server = app.listen(PORT, function() {
  var host = server.address().address;
  var port = server.address().port;

  console.log('Example app listening at http://%s:%s', host, port);
});

var handleFiles = function() {
  if (FILE_TO_WATCH) {
    var watch = fs.watch(FILE_TO_WATCH, function(ev, fname) {
      // What should actually be done when transmitting: emit on an event and
      // log to console.
      var transmitMessage = function() {
        events.refreshme.emit('sendMessage', 'sendMessage', ev);
        console.log('File change detected and transmitted:', ev);
      };

      // If we are given a command to run (e.g., re-render the changed file), do
      // so asynchronously and send the message when completed, in the callback.
      // If no command is needed, transmit the message right away.
      if (COMMAND_TO_RUN) {
        child_process.exec(COMMAND_TO_RUN, function(err, stdout, stderr) {
          console.log('Command run. Output: \n' + stdout);
          if (stderr) {
            console.log('Command resulted in ERROR:', stderr);
          }
          transmitMessage();
        });
      } else {
        transmitMessage();
      }

      // If the file was renamed (vim saving does this, e.g., see
      // https://github.com/nodejs/node-v0.x-archive/issues/3640#issuecomment-6806347),
      // the watch will no longer work. Recreate it.
      if (ev === 'rename') {
        handleFiles();
      }
    });
  }
}
handleFiles();


text:
#lang pollen

◊h1{Take Three. Automate the world.}

◊section{
This take is all about infrastructure to ease Pollen authoring. Make sure you installed and set up ◊a['((href "https://nodejs.org"))]{node.js}. If you are using Internet Explorer or Edge or any browser that doesn't support EventSource (listed in red at ◊a['((href "http://caniuse.com/#feat=eventsource"))]{Can I Use}), pay attention to the instructions for you.

Run ◊code{$ node server take3.html.pm "POLLEN=TESTING raco pollen render take3.html"}. This starts the webserver and auxiliary code to watch this ◊code{take3.html.pm} file for changes.

Open ◊a['((href "http://localhost:3000/take3.html"))]{localhost:3000/take3.html} and position your browser window so you can watch it while you edit this document.

Now, edit this Pollen file and save it. In a second or three, you'll see your browser refresh with the new contents.

Caveat: for annoying technical reasons, the page will update twice, in rapid succession, every time you save this Pollen file.

This works fine now..... under Ubuntu Linux

I wonder if this will make a difference
}


text: POLLEN="TESTING" raco pollen render take3.html && curl -f -s -X POST http://localhost:3000/events/refreshme -d 'change'


text:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>◊select['h1 doc]</title>
<link rel="stylesheet" href="/public/tufte.css">

◊(if (getenv "POLLEN") "
<script src='/public/eventsource.min.js'></script>
<script>
var id = 'refreshme';
var testEvent = new EventSource('/events/' + id);

testEvent.addEventListener('sendMessage', function(event) {
  var data = JSON.parse(event.data);
  console.log('Data received:', data);
  if (data === 'change' || data === 'rename') {
    window.location.reload();
  }
});
</script>
" "")
</head>

<article>
◊(->html doc)
</article>


text:
<!DOCTYPE html>

<meta charset="UTF-8">
<title>Take Three. Automate the world.</title>
<link rel="stylesheet" href="/public/tufte.css">

Take Three. Automate the world.

This take is all about infrastructure to ease Pollen authoring. Make sure you installed and set up node.js. If you are using Internet Explorer or Edge or any browser that doesn't support EventSource (listed in red at Can I Use), pay attention to the instructions for you.

Run $ node server take3.html.pm "POLLEN=TESTING raco pollen render take3.html". This starts the webserver and auxiliary code to watch this take3.html.pm file for changes.

Open localhost:3000/take3.html and position your browser window so you can watch it while you edit this document.

Now, edit this Pollen file and save it. In a second or three, you'll see your browser refresh with the new contents.

Caveat: for annoying technical reasons, the page will update twice, in rapid succession, every time you save this Pollen file.

This works fine now..... under Ubuntu Linux

I wonder if this will make a difference


text:
@charset "UTF-8";

/* Import ET Book styles
   adapted from https://github.com/edwardtufte/et-book/blob/gh-pages/et-book.css */

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot");
    src: url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.woff") format("woff"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.ttf") format("truetype"), url("et-book/et-book-roman-line-figures/et-book-roman-line-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot");
    src: url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.woff") format("woff"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.ttf") format("truetype"), url("et-book/et-book-display-italic-old-style-figures/et-book-display-italic-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: italic;
    font-display: swap;
}

@font-face {
    font-family: "et-book";
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot");
    src: url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.woff") format("woff"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.ttf") format("truetype"), url("et-book/et-book-bold-line-figures/et-book-bold-line-figures.svg#etbookromanosf") format("svg");
    font-weight: bold;
    font-style: normal;
    font-display: swap;
}

@font-face {
    font-family: "et-book-roman-old-style";
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot");
    src: url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.eot?#iefix") format("embedded-opentype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.woff") format("woff"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.ttf") format("truetype"), url("et-book/et-book-roman-old-style-figures/et-book-roman-old-style-figures.svg#etbookromanosf") format("svg");
    font-weight: normal;
    font-style: normal;
    font-display: swap;
}

/* Tufte CSS styles */
html {
    font-size: 15px;
}

body {
    width: 87.5%;
    margin-left: auto;
    margin-right: auto;
    padding-left: 12.5%;
    font-family: et-book, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
    background-color: #fffff8;
    color: #111;
    max-width: 1400px;
    counter-reset: sidenote-counter;
}

h1 {
    font-weight: 400;
    margin-top: 4rem;
    margin-bottom: 1.5rem;
    font-size: 3.2rem;
    line-height: 1;
}

h2 {
    font-style: italic;
    font-weight: 400;
    margin-top: 2.1rem;
    margin-bottom: 1.4rem;
    font-size: 2.2rem;
    line-height: 1;
}

h3 {
    font-style: italic;
    font-weight: 400;
    font-size: 1.7rem;
    margin-top: 2rem;
    margin-bottom: 1.4rem;
    line-height: 1;
}

hr {
    display: block;
    height: 1px;
    width: 55%;
    border: 0;
    border-top: 1px solid #ccc;
    margin: 1em 0;
    padding: 0;
}

p.subtitle {
    font-style: italic;
    margin-top: 1rem;
    margin-bottom: 1rem;
    font-size: 1.8rem;
    display: block;
    line-height: 1;
}

.numeral {
    font-family: et-book-roman-old-style;
}

.danger {
    color: red;
}

article {
    padding: 5rem 0rem;
}

section {
    padding-top: 1rem;
    padding-bottom: 1rem;
}

p,
ol,
ul {
    font-size: 1.4rem;
    line-height: 2rem;
}

p {
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    padding-right: 0;
    vertical-align: baseline;
}

/* Chapter Epigraphs */
div.epigraph {
    margin: 5em 0;
}

div.epigraph > blockquote {
    margin-top: 3em;
    margin-bottom: 3em;
}

div.epigraph > blockquote,
div.epigraph > blockquote > p {
    font-style: italic;
}

div.epigraph > blockquote > footer {
    font-style: normal;
}

div.epigraph > blockquote > footer > cite {
    font-style: italic;
}
/* end chapter epigraphs styles */

blockquote {
    font-size: 1.4rem;
}

blockquote p {
    width: 55%;
    margin-right: 40px;
}

blockquote footer {
    width: 55%;
    font-size: 1.1rem;
    text-align: right;
}

section > p,
section > footer,
section > table {
    width: 55%;
}

/* 50 + 5 == 55, to be the same width as paragraph */
section > ol,
section > ul {
    width: 50%;
    -webkit-padding-start: 5%;
}

li:not(:first-child) {
    margin-top: 0.25rem;
}

figure {
    padding: 0;
    border: 0;
    font-size: 100%;
    font: inherit;
    vertical-align: baseline;
    max-width: 55%;
    -webkit-margin-start: 0;
    -webkit-margin-end: 0;
    margin: 0 0 3em 0;
}

figcaption {
    float: right;
    clear: right;
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.6;
    vertical-align: baseline;
    position: relative;
    max-width: 40%;
}

figure.fullwidth figcaption {
    margin-right: 24%;
}

/* Links: replicate underline that clears descenders */
a:link,
a:visited {
    color: inherit;
}

.no-tufte-underline:link {
    background: unset;
    text-shadow: unset;
}

a:link, .tufte-underline, .hover-tufte-underline:hover {
    text-decoration: none;
    background: -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(#fffff8, #fffff8), -webkit-linear-gradient(currentColor, currentColor);
    background: linear-gradient(#fffff8, #fffff8), linear-gradient(#fffff8, #fffff8), linear-gradient(currentColor, currentColor);
    -webkit-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    -moz-background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-size: 0.05em 1px, 0.05em 1px, 1px 1px;
    background-repeat: no-repeat, no-repeat, repeat-x;
    text-shadow: 0.03em 0 #fffff8, -0.03em 0 #fffff8, 0 0.03em #fffff8, 0 -0.03em #fffff8, 0.06em 0 #fffff8, -0.06em 0 #fffff8, 0.09em 0 #fffff8, -0.09em 0 #fffff8, 0.12em 0 #fffff8, -0.12em 0 #fffff8, 0.15em 0 #fffff8, -0.15em 0 #fffff8;
    background-position: 0% 93%, 100% 93%, 0% 93%;
}

@media screen and (-webkit-min-device-pixel-ratio: 0) {
    a:link, .tufte-underline, .hover-tufte-underline:hover {
        background-position-y: 87%, 87%, 87%;
    }
}

a:link::selection,
a:link::-moz-selection {
    text-shadow: 0.03em 0 #b4d5fe, -0.03em 0 #b4d5fe, 0 0.03em #b4d5fe, 0 -0.03em #b4d5fe, 0.06em 0 #b4d5fe, -0.06em 0 #b4d5fe, 0.09em 0 #b4d5fe, -0.09em 0 #b4d5fe, 0.12em 0 #b4d5fe, -0.12em 0 #b4d5fe, 0.15em 0 #b4d5fe, -0.15em 0 #b4d5fe;
    background: #b4d5fe;
}

/* Sidenotes, margin notes, figures, captions */
img {
    max-width: 100%;
}

.sidenote,
.marginnote {
    float: right;
    clear: right;
    margin-right: -60%;
    width: 50%;
    margin-top: 0;
    margin-bottom: 0;
    font-size: 1.1rem;
    line-height: 1.3;
    vertical-align: baseline;
    position: relative;
}

.sidenote-number {
    counter-increment: sidenote-counter;
}

.sidenote-number:after,
.sidenote:before {
    font-family: et-book-roman-old-style;
    position: relative;
    vertical-align: baseline;
}

.sidenote-number:after {
    content: counter(sidenote-counter);
    font-size: 1rem;
    top: -0.5rem;
    left: 0.1rem;
}

.sidenote:before {
    content: counter(sidenote-counter) " ";
    font-size: 1rem;
    top: -0.5rem;
}

blockquote .sidenote,
blockquote .marginnote {
    margin-right: -82%;
    min-width: 59%;
    text-align: left;
}

div.fullwidth,
table.fullwidth {
    width: 100%;
}

div.table-wrapper {
    overflow-x: auto;
    font-family: "Trebuchet MS", "Gill Sans", "Gill Sans MT", sans-serif;
}

.sans {
    font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif;
    letter-spacing: .03em;
}

code, pre > code {
    font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
    font-size: 1.0rem;
    line-height: 1.42;
    -webkit-text-size-adjust: 100%; /* Prevent adjustments of font size after orientation changes in iOS. See https://github.com/edwardtufte/tufte-css/issues/81#issuecomment-261953409 */
}

.sans > code {
    font-size: 1.2rem;
}

h1 > code,
h2 > code,
h3 > code {
    font-size: 0.80em;
}

.marginnote > code,
.sidenote > code {
    font-size: 1rem;
}

pre > code {
    font-size: 0.9rem;
    width: 52.5%;
    margin-left: 2.5%;
    overflow-x: auto;
    display: block;
}

pre.fullwidth > code {
    width: 90%;
}

.fullwidth {
    max-width: 90%;
    clear:both;
}

span.newthought {
    font-variant: small-caps;
    font-size: 1.2em;
}

input.margin-toggle {
    display: none;
}

label.sidenote-number {
    display: inline;
}

label.margin-toggle:not(.sidenote-number) {
    display: none;
}

.iframe-wrapper {
    position: relative;
    padding-bottom: 56.25%; /* 16:9 */
    padding-top: 25px;
    height: 0;
}

.iframe-wrapper iframe {
    position: absolute;
    top: 0;
    left: 0;
    width: 100%;
    height: 100%;
}

@media (max-width: 760px) {
    body {
        width: 84%;
        padding-left: 8%;
        padding-right: 8%;
    }

    hr,
    section > p,
    section > footer,
    section > table {
        width: 100%;
    }

    pre > code {
        width: 97%;
    }

    section > ol {
        width: 90%;
    }

    section > ul {
        width: 90%;
    }

    figure {
        max-width: 90%;
    }

    figcaption,
    figure.fullwidth figcaption {
        margin-right: 0%;
        max-width: none;
    }

    blockquote {
        margin-left: 1.5em;
        margin-right: 0em;
    }

    blockquote p,
    blockquote footer {
        width: 100%;
    }

    label.margin-toggle:not(.sidenote-number) {
        display: inline;
    }

    .sidenote,
    .marginnote {
        display: none;
    }

    .margin-toggle:checked + .sidenote,
    .margin-toggle:checked + .marginnote {
        display: block;
        float: left;
        left: 1rem;
        clear: both;
        width: 95%;
        margin: 1rem 2.5%;
        vertical-align: baseline;
        position: relative;
    }

    label {
        cursor: pointer;
    }

    div.table-wrapper,
    table {
        width: 85%;
    }

    img {
        width: 100%;
    }
}


text:
<!DOCTYPE html>

<meta charset="UTF-8">
<title>Take Two. Or, some things are harder than they appear.</title>
<link rel="stylesheet" href="tufte.css">

<decoded-root>
Take Two. Or, some things are harder than they appear.

Tufte CSS' has nice sidenotes, but each sidenote is made up of three side-by-side tags: a <label> to contain a unique identifier, a fake <input>, and a span tag containing the sidenote's content. We'd like to make a single sidenote tag in Pollen that renders to that.<input id="sidenoteReference" class="margin-toggle" type="checkbox"/>Here's that sidenote!

None of the magic from Take One helps tell us how to expand a single tag into three adjacent ones, unless it's something stupid like combining the three into a single parent tag (NE VEUX PAS<stupid-sidenote><input id="although" class="margin-toggle" type="checkbox"/>Although it would work.</stupid-sidenote>). So we need some new magic, courtesy of Matthew Butterick's example code: the splice function and a custom root function.

We also desperately need to automatically detect paragraphs and insert <p> tags.

Build me with

$ raco pollen render take2.html

Then open take2.html in your browser.

</decoded-root>


text:
#lang pollen
◊(require txexpr)
◊(require pollen/decode)

◊(define (sidenote label . xs)
  `(splice-me
     (label ((for ,label) (class "margin-toggle sidenote-number")))
     (input ((id ,label) (class "margin-toggle")(type "checkbox")))
     (span ((class "sidenote")) ,@xs)))

◊;literally the same as above
◊(define (stupid-sidenote label . xs)
  `(stupid-sidenote
     (label ((for ,label) (class "margin-toggle sidenote-number")))
     (input ((id ,label) (class "margin-toggle")(type "checkbox")))
     (span ((class "sidenote")) ,@xs)))

◊(define (splice xs)
  (apply append (for/list ([x (in-list xs)])
                  (if (and (txexpr? x) (member (get-tag x) '(splice-me)))
                      (get-elements x)
                      (list x)))))

◊(define (root . xs)
  (decode `(decoded-root ,@xs)
          #:txexpr-elements-proc (compose1 detect-paragraphs splice)
          #:exclude-tags '(pre)
          ))

◊h1{Take Two. Or, some things are harder than they appear.}

◊section{
Tufte CSS' has nice sidenotes, but each sidenote is made up of three side-by-side tags: a ◊code{<label>} to contain a unique identifier, a fake ◊code{<input>}, and a ◊code{span} tag containing the sidenote's content. We'd like to make a single ◊code{sidenote} tag in Pollen that renders to that.◊sidenote["sidenoteReference"]{Here's that sidenote!}

None of the magic from Take One helps tell us how to expand a single tag into three adjacent ones, unless it's something stupid like combining the three into a single parent tag (NE VEUX PAS◊stupid-sidenote["although"]{Although it would work.}). So we need some new magic, courtesy of Matthew Butterick's ◊a['((href "http://unitscale.com/mb/technique/pollen.rkt.html"))]{example code}: the ◊code{splice} function and a custom ◊code{root} function.

We also desperately need to automatically detect paragraphs and insert ◊code{<p>} tags.

Build me with ◊pre{
$ raco pollen render take2.html
}
Then open ◊code{take2.html} in your browser.
}


text:
<!DOCTYPE html>
<head>
<meta charset="UTF-8">
<title>◊select['h1 doc]</title>
<link rel="stylesheet" href="tufte.css">
</head>

<article>
◊(->html doc)
</article>


text:
html { font-size: 15px; }

body { width: 87.5%;
       margin-left: auto;
       margin-right: auto;
       padding-left: 12.5%;
       font-family: ETBembo, Palatino, "Palatino Linotype", "Palatino LT STD", "Book Antiqua", Georgia, serif;
       background-color: #fffff8;
       color: #111;
       max-width: 1400px;
       counter-reset: sidenote-counter; }

h1 { font-weight: 400;
     margin-top: 4rem;
     margin-bottom: 1.5rem;
     font-size: 3.2rem;
     line-height: 1; }

h2 { font-style: italic;
     font-weight: 400;
     margin-top: 2.1rem;
     margin-bottom: 0;
     font-size: 2.2rem;
     line-height: 1; }

h3 { font-style: italic;
     font-weight: 400;
     font-size: 1.7rem;
     margin-top: 2rem;
     margin-bottom: 0;
     line-height: 1; }

p.subtitle { font-style: italic;
             margin-top: 1rem;
             margin-bottom: 1rem;
             font-size: 1.8rem;
             display: block;
             line-height: 1; }

table { width: 98%;
        clear: left;
        text-align: right;
        font-size: 1.2rem;
        line-height: 1.4;
        margin: 1.4rem 1%;
        border-collapse: separate;
        border-spacing: 0 5px;
        -webkit-font-feature-settings: 'tnum'; /* This is technically redundant */
        -moz-font-feature-settings: 'tnum';
        -ms-font-feature-settings: 'tnum'; }

thead th { border-bottom: 1px solid #AAAAAA;
           font-weight: 400;
           border-collapse: separate;
           border-spacing: 5px 5px; }

td.text { text-align: left; }

span.table-label { padding-top: 8px; } /* to maintain height relative to table header row */

table.booktabs { width: auto;
                 margin: 0 auto;
                 border-spacing: 0px;
                 border-top: 2px solid #333333;
                 border-bottom: 2px solid #333333; }

.booktabs th { border-bottom: 1px solid #333333;
               padding: 0.65ex 0.5em 0.4ex 0.5em;
               font-weight: normal;
               text-align: center; }

.booktabs th.cmid { border-bottom: 1px solid #666666; }

.booktabs th.nocmid { border-bottom: none; }

.booktabs tbody tr:first-child td { padding-top: 0.65ex; } /* add space between thead row and tbody */

.booktabs td { padding-left: 0.5em;
               padding-right: 0.5em;
               text-align: left; }

.booktabs caption { font-size: 90%;
                    text-align: left;
                    width: auto;
                    margin-left: auto;
                    margin-right: auto;
                    margin-top: 1ex;
                    caption-side: top; }

.booktabs tbody tr td.l { text-align: left !important; }
.booktabs tbody tr td.c { text-align: center !important; }
.booktabs tbody tr td.r { text-align: right !important; }

article { position: relative;
          padding: 5rem 0rem; }

section { padding-top: 1rem;
          padding-bottom: 1rem; }

p, ol, ul { font-size: 1.4rem; }

p { line-height: 2rem;
    margin-top: 1.4rem;
    margin-bottom: 1.4rem;
    padding-right: 0;
    vertical-align: baseline; }

blockquote p { font-size: 1.1rem;
               width: 50%; }

blockquote footer { width: 50%;
                    text-align: right; }

ul { width: 45%;
     -webkit-padding-start: 5%;
     -webkit-padding-end: 5%;
     list-style-type: none; }

li { padding: 0.5rem 0; }

figure { max-width: 55%;
         -webkit-margin-start: 0;
         -webkit-margin-end: 0;
         margin-bottom: 3em; }

figcaption { float: right;
             clear: right;
             margin-right: -48%;
             margin-top: 0;
             margin-bottom: 0;
             font-size: 1.0rem;
             line-height: 1.6;
             vertical-align: baseline;
             position: relative; }

figure.fullwidth figcaption { margin-right: 24%; }

a { color: #111;
    text-decoration: none;
    border-bottom: 1px solid #777;
    padding-bottom: 1px; }

img { max-width: 100%; }

.sidenote, .marginnote { float: right;
                         clear: right;
                         margin-right: -60%;
                         width: 50%;
                         margin-top: 0;
                         margin-bottom: 0;
                         font-size: 1.0rem;
                         line-height: 1.6;
                         vertical-align: baseline;
                         position: relative; }

.table-caption { float:right;
                 clear:right;
                 margin-right: -60%;
                 width: 50%;
                 margin-top: 0;
                 margin-bottom: 0;
                 font-size: 1.0rem;
                 line-height: 1.6; }

.sidenote-number { counter-increment: sidenote-counter; }

.sidenote-number:after, .sidenote:before { content: counter(sidenote-counter) " ";
                                           position: relative;
                                           vertical-align: baseline;
                                           color: #f00000; }

.sidenote-number:after { content: counter(sidenote-counter);
                         font-size: 0.9rem;
                         top: -0.5rem;
                         left: 0.1rem; }

.sidenote:before { content: counter(sidenote-counter) ". ";
                   position: absolute;
                   /* 100% refers to the computed width of the number, so this transform
                    * shifts the number just outside the left edge of the sidenote box,
                    * with a buffer of 0.25rem, no matter how many digits the number has. */
                   -webkit-transform: translateX(-100%) translateX(-0.25rem);
                   -ms-transform: translateX(-100%) translateX(-0.25rem);
                   transform: translateX(-100%) translateX(-0.25rem); }

p, footer, div.table-wrapper { width: 55%; }

@media screen and (max-width: 760px) { p, footer { width: 90%; }
                                       pre.code { width: 87.5%; }
                                       ul { width: 85%; }
                                       figure { max-width: 90%; }
                                       figcaption, figure.fullwidth figcaption { margin-right: 0%; }
                                       blockquote p, blockquote footer { width: 90%; }}

.sans { font-family: "Gill Sans", "Gill Sans MT", Calibri, sans-serif; }

.code { font-family: Consolas, "Liberation Mono", Menlo, Courier, monospace;
        font-size: 1.125rem;
        line-height: 1.6; }

h1 .code, h2 .code, h3 .code { font-size: 0.80em; }

.marginnote .code, .sidenote .code { font-size: 1rem; }

pre.code { width: 52.5%;
           padding-left: 2.5%;
           overflow-x: scroll; }

.fullwidth { max-width: 90%; }

span.newthought { font-variant: small-caps;
                  font-size: 1.2em; }

input.margin-toggle { display: none; }

label.sidenote-number { display: inline; }

label.margin-toggle:not(.sidenote-number) { display: none; }

@media (max-width: 760px) { label.margin-toggle:not(.sidenote-number) { display: inline; }
                            .sidenote, .marginnote { display: none; }
                            .margin-toggle:checked + .sidenote,
                            .margin-toggle:checked + .marginnote { display: block;
                                                                   float: left;
                                                                   left: 1rem;
                                                                   clear: both;
                                                                   width: 95%;
                                                                   margin: 1rem 2.5%;
                                                                   vertical-align: baseline;
                                                                   position: relative; }
                            label { cursor: pointer; }
                            pre.code { width: 90%;
                                       padding: 0; }
                            .table-caption { display: block;
                                             float: right;
                                             clear: both;
                                             width: 98%;
                                             margin-top: 1rem;
                                             margin-bottom: 0.5rem;
                                             margin-left: 1%;
                                             margin-right: 1%;
                                             vertical-align: baseline;
                                             position: relative; }
                            table, table.booktabs { width: 85%; }
                            img { width: 100%; } }


text:
#lang pollen
◊(define (emphatic . xs) `(em ,@xs))
◊(define (linky url . xs) `(a ((href ,url)) ,@xs))

◊h1{Take One. Or, Let's Try To Get the Basics.}

Let's try and make the basics work. How do we do things like the tutorials on Pollen markup: ◊emphatic{italicize things}. How do we make ◊linky["http://github.com"]{links to cool things}? Cool!

Observe that ◊emphatic{this call} produces the same result as ◊(emphatic "this call"). And Pollen, when targeting HTML, can deal with attributes in the same way: ◊span['((class "hidden"))]{this span} produces the same output as ◊(span '((class "hidden")) "this span"). But watch out! If you ◊code{define} a tag like we did with ◊code{linky} to make links, you can't just randomly pass attributes in this way. Since ◊code{linky} is expecting its first argument to be a string URL, not a list, this won't even compile: ◊code{(missing ◊lozenge{})linky['((class "hidden") (href "/"))]{won't work}}.

Build me with ◊pre{
$ raco pollen render take1.html
}
Then open `take1.html` in your browser.


text:
<!DOCTYPE html>

<meta charset="UTF-8">
<title>Take One. Or, Let's Try To Get the Basics.</title>
<link rel="stylesheet" href="tufte.css">

<root>
Take One. Or, Let's Try To Get the Basics.

Let's try and make the basics work. How do we do things like the tutorials on Pollen markup: italicize things. How do we make links to cool things? Cool!

Observe that this call produces the same result as this call. And Pollen, when targeting HTML, can deal with attributes in the same way: this span produces the same output as this span. But watch out! If you define a tag like we did with linky to make links, you can't just randomly pass attributes in this way. Since linky is expecting its first argument to be a string URL, not a list, this won't even compile: (missing <lozenge></lozenge>)linky['((class "hidden") (href "/"))]{won't work}.

Build me with
$ raco pollen render take1.html

Then open `take1.html` in your browser.
</root>


text:
#+TITLE: X resources

** XFT settings.

Necessary to improve the xft fonts.

#+begin_src conf :tangle ~/.Xresources :padline yes
Xft.dpi: 96
Xft.antialias: true
Xft.rgba: rgb
Xft.hinting: true
Xft.hintstyle: hintfull
Xft.autohint: 0
Xft.lcdfilter: lcddefault
#+end_src

** URxvt Customization and Optimization.

*** Start Urxvt as a login shell.

#+begin_src conf :tangle ~/.Xresources :padline no
URxvt*loginShell: true
#+end_src

*** Enable 256 color support.

I use gnu-screen so this is helpful.

#+begin_src conf :tangle ~/.Xresources :padline no
URxvt*termName: screen-256color
#+end_src

*** Scrolling.

Someone who really need scroll bars?

#+begin_src conf :tangle ~/.Xresources :padline no
URxvt*scrollBar: false
URxvt*scrollBar_right: false
URxvt*scrollBar_floating: false
#+end_src

Stop automatic scrolling when going back in the buffer.

1. do not scroll to bottom when tty receives output.
2. scroll in relation to buffer (with mouse scroll or Shift+Page Up)
3. scroll back to the bottom on keypress.

#+BEGIN_SRC conf :tangle ~/.Xresources
URxvt*scrollTtyOutput: false
URxvt*scrollWithBuffer: true
URxvt*scrollTtyKeypress: true
#+END_SRC

*** Perl extensions

**** Enable the extensions features for Urxvt.

#+BEGIN_SRC conf :tangle ~/.Xresources
URxvt.perl-ext-common: default,clipboard,url-select,font-size
#+END_SRC

**** Url-select

I want to select and open URLs in my browser (Conkeror) without using the mouse, by this we installed [[https://www.archlinux.org/packages/community/any/urxvt-perls/][urxvt-perls]]
from Arch/community repo.

#+begin_src conf :tangle ~/.Xresources :padline yes
URxvt.url-select.launcher:  conkeror
URxvt.url-select.underline: true
URxvt.keysym.C-i:           perl:url-select:select_next
#+end_src

**** Font size

Changing the font size on the fly with keyboard shortcuts. To use this you have
to install [[https://aur.archlinux.org/packages/urxvt-font-size-git/][urxvt-font-size-git]] from Archlinux/Aur.

#+BEGIN_SRC conf :tangle ~/.Xresources
URxvt.keysym.C-equal : perl:font-size:increase
URxvt.keysym.C-minus : perl:font-size:decrease
#+END_SRC

**** Clipboard

Enable Copy/Pasting from Urxvt with =^c= =^v= . To use this you have to
install [[https://www.archlinux.org/packages/community/any/urxvt-perls/][urxvt-perls]] from Arch/community repo.

#+BEGIN_SRC conf :tangle ~/.Xresources
URxvt.keysym.C-c: perl:clipboard:copy
URxvt.keysym.C-v: perl:clipboard:paste
#+END_SRC

*** Disable Keycap Picture insert mode

Disable all the urxvt functionalities (input of ☺ unicodes etc..) associated with the =ctrl+shift= keys.

#+BEGIN_SRC conf :tangle ~/.Xresources
URxvt.iso14755: false
URxvt.iso14755_52: false
#+END_SRC

*** Font Appearance.

I use Anonymous Pro as my font choice.

#+begin_src conf :tangle ~/.Xresources :padline yes
URxvt*font:                 xft:Anonymous Pro:regular:size=13
URxvt*imFont:               xft:Anonymous Pro:regular:size=13
URxvt*boldFont:             xft:Anonymous Pro:bold:size=13
URxvt*italicFont:           xft:Anonymous Pro:italic:size=13
URxvt*boldItalicFont:       xft:Anonymous Pro:bold:italic:size=13
#+end_src

*** Zenburn color-scheme.

The Color scheme that Changed the World!

#+begin_src conf :tangle ~/.Xresources :padline yes
URxvt*background: #3F3F3F
URxvt*foreground: #DCDCCC
URxvt*cursorColor: #DCDCCC
URxvt*cursorColor2: #3F3F3F
URxvt*colorUL: #8CD0D3
URxvt*underlineColor: #F0DFAF
URxvt*colorBD: #E0CF9F
URxvt*colorIT: #656555

!! black dark/light
URxvt*color0: #3F3F3F
URxvt*color8: #5F5F5F
!! red dark/light
URxvt*color1: #BC8383
URxvt*color9: #CC9393
!! green dark/light
URxvt*color2: #5F7F5F
URxvt*color10: #7F9F7F
!! yellow dark/light
URxvt*color3: #E0CF9F
URxvt*color11: #F0DFAF
!! blue dark/light
URxvt*color4: #7CB8BB
URxvt*color12: #8CD0D3
!! magenta dark/light
URxvt*color5: #DC8CC3
URxvt*color13: #DC8CC3
!! cyan dark/light
URxvt*color6: #93E0E3
URxvt*color14: #93E0E3
!! white dark/light
URxvt*color7: #DCDCCC
URxvt*color15: #FFFFFF
#+end_src

** XMESSAGE

Configure the appearance of xmessage, I like red background and yellow foreground.

#+begin_src conf :tangle ~/.Xresources :padline yes
Xmessage*font: -*-terminus-medium-r-*-*-14-*-*-*-*-*-iso10646-1
Xmessage*background: red
Xmessage*foreground: yellow
Xmessage*form.*.shapeStyle: rectangle
Xmessage*Scrollbar.width: 1
Xmessage*Scrollbar.borderWidth: 0
Xmessage*Buttons: OK
Xmessage*defaultButton: OK
#+end_src

repo_language: Shell

file_name: PKGBUILD

mime_type: text/plain


text:
#+TITLE: My browser config

#+ATTR_HTML: :alt conkeror.png image :title conkeror :align left :width 380px :hight 280px
[[file:images/conkeror.png]]

** Appearance

1. Set path for themes.
2. Unload "Default" theme.
3. Load theme [[https://github.com/ivoarch/conkeror-theme-zenburn][conkeror-theme-zenburn]].

#+BEGIN_SRC js :tangle ~/.conkerorrc
theme_load_paths.unshift("~/.conkeror/themes/");
theme_unload("default");
theme_load("conkeror-theme-zenburn");
#+END_SRC

** New buffers instead of new windows.

I need this for open URLs from GNU Emacs in Conkeror in a new buffer. See [[http://www.emacswiki.org/emacs/BrowseUrl][this link for more info.]]

#+BEGIN_SRC js :tangle ~/.conkerorrc
url_remoting_fn = load_url_in_new_buffer;
#+END_SRC

** Completion

I use completion system for - =history=, =bookamrks=, =webjumps= and the =minibuffer=.

#+BEGIN_SRC js :tangle ~/.conkerorrc
url_completion_use_history = true;
url_completion_use_bookmarks = true;
url_completion_use_webjumps = true;
minibuffer_auto_complete_default = true;
#+END_SRC

** Session and History settings

Enable auto save session and make it load automatically at startup.

#+BEGIN_SRC js :tangle ~/.conkerorrc
require("session.js");
session_auto_save_auto_load = true;
#+END_SRC

Setup how long in days, history entries are kept before being automatically expired.

#+BEGIN_SRC js :tangle ~/.conkerorrc
session_pref('browser.history_expire_days', 30);
#+END_SRC

** Enabling the Password Manager

#+BEGIN_SRC js :tangle ~/.conkerorrc
session_pref("signon.rememberSignons", true);
session_pref("signon.expireMasterPassword", false);
session_pref("signon.SignonFileName", "signons.txt");
Components.classes['@mozilla.org/login-manager;1']
    .getService(Components.interfaces.nsILoginManager);
#+END_SRC

** Modeline
*** Widgets

I disabled only the clock widget, everything else is enabled.

#+BEGIN_SRC js :tangle ~/.conkerorrc
require("mode-line.js");

remove_hook("mode_line_hook", mode_line_adder(clock_widget));

add_hook("mode_line_hook", mode_line_adder(buffer_icon_widget), true);
add_hook("mode_line_hook", mode_line_adder(loading_count_widget), true);
add_hook("mode_line_hook", mode_line_adder(buffer_count_widget), true);
add_hook("mode_line_hook", mode_line_adder(zoom_widget));
add_hook("mode_line_hook", mode_line_adder(downloads_status_widget));
#+END_SRC

*** Favicons

Activate the favicons in the modeline.

#+BEGIN_SRC js :tangle ~/.conkerorrc
require("favicon.js");
add_hook("mode_line_hook", mode_line_adder(buffer_icon_widget), true);
read_buffer_show_icons = true;
#+END_SRC

*** Hinting

Displaying the url of a link in hints mode.

#+BEGIN_SRC js :tangle ~/.conkerorrc
hints_display_url_panel = true;
#+END_SRC

Display information about the currently selected hint.

#+BEGIN_SRC js :tangle ~/.conkerorrc
hints_minibuffer_annotation_mode(true);
#+END_SRC

** Hinting

I want to use letters instead of numbers.

#+BEGIN_SRC js :tangle ~/.conkerorrc
hint_digits="asdfghjkl";
#+END_SRC

** Set default download directory

This sets the default download directory to =~/Downloads=.

#+BEGIN_SRC js :tangle ~/.conkerorrc
cwd = get_home_directory();
cwd = make_file("/home/ivo/Downloads");
#+END_SRC

*** Other

Don't use a new window for downloads.

#+BEGIN_SRC js :tangle ~/.conkerorrc
download_buffer_automatic_open_target=OPEN_NEW_BUFFER_BACKGROUND;
#+END_SRC

** External programs for handling various mime types in conkeror
*** Automatically open pdf files with Xpdf.

#+BEGIN_SRC js :tangle ~/.conkerorrc
content_handlers.set("application/pdf", content_handler_open_default_viewer);
external_content_handlers.set("application/pdf", "xpdf");
#+END_SRC

*** Automatically open documents with Libreoffice.

For a complete list checkout this TechNet [[http://technet.microsoft.com/en-us/library/ee309278%2528office.12%2529.aspx][article]] .

#+BEGIN_SRC js :tangle ~/.conkerorrc
external_content_handlers.set(
      "application/vnd.ms-excel",
      "libreoffice"
);
external_content_handlers.set(
      "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
      "libreoffice"
);
external_content_handlers.set(
      "application/vnd.openxmlformats-officedocument.presentationml.presentation",
      "libreoffice"
);
external_content_handlers.set(
      "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
      "libreoffice"
);
#+END_SRC

*** Open mailto links with Emacs. Get the script from [[https://raw2.github.com/ivoarch/bin/master/mail/emacs-mailto-handler.sh][here]].

#+BEGIN_SRC js :tangle ~/.conkerorrc
set_protocol_handler("mailto", make_file("~/bin/mail/emacs-mailto-handler.sh"));
#+END_SRC

*** Open magnet links with Transmission.

#+BEGIN_SRC js :tangle ~/.conkerorrc
set_protocol_handler("magnet", find_file_in_path("transmission-gtk"));
#+END_SRC

*** Automatically open torrent files with Transmission.

#+BEGIN_SRC js :tangle ~/.conkerorrc
content_handlers.set("application/x-bittorrent", content_handler_open);
external_content_handlers.set("application/x-bittorrent", "transmission-gtk");
#+END_SRC

*** View source in emacs.

#+BEGIN_SRC js :tangle ~/.conkerorrc
editor_shell_command="emacsclient -ca emacs";
view_source_use_external_editor = true;
#+END_SRC

** Extensions

1. Disable extension compatability checking.
2. Allow installing extension from any source.
3. Enable security updates.

#+BEGIN_SRC js :tangle ~/.conkerorrc
session_pref('extensions.checkCompatibility', false);
session_pref("xpinstall.whitelist.required", false);
user_pref("extensions.checkUpdateSecurity", true);
#+END_SRC

*** Firebug

#+BEGIN_SRC js :tangle ~/.conkerorrc
define_variable("firebug_url",
    "http://getfirebug.com/releases/lite/1.2/firebug-lite-compressed.js");

function firebug (I) {
    var doc = I.buffer.document;
    var script = doc.createElement('script');
    script.setAttribute('type', 'text/javascript');
    script.setAttribute('src', firebug_url);
    script.setAttribute('onload', 'firebug.init();');
    doc.body.appendChild(script);
}
    interactive("firebug", "open firebug lite", firebug);
#+END_SRC

*** Https-everywhere

#+BEGIN_SRC js :tangle ~/.conkerorrc
if ('@eff.org/https-everywhere;1' in Cc) {
    interactive("https-everywhere-options-dialog",
                "Open the HTTPS Everywhere options dialog.",
                function (I) {
                    window_watcher.openWindow(
                        null, "chrome://https-everywhere/content/preferences.xul",
                        "", "chrome,titlebar,toolbar,centerscreen,resizable", null);
                });
}
#+END_SRC

*** Adblock-plus

#+BEGIN_SRC js :tangle ~/.conkerorrc
require("adblockplus");
#+END_SRC

** My webjumps
*** Arch linux
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("arch/forums", "http://bbs.archlinux.org");
define_webjump("arch/wiki", "http://wiki.archlinux.org/index.php?search=%s");
define_webjump("arch/aur", "http://aur.archlinux.org/packages.php?O=0&K=%s");
define_webjump("arch/packages",
               "https://www.archlinux.org/packages/?sort=&q=%s&limit=50",
               $alternative="https://packages.archlinux.org");
#+END_SRC

*** Questions
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("linux-questions","http://www.linuxquestions.org/questions/");
define_webjump("gmane", "http://gmane.org/find.php?list=%s");
define_webjump("hackernews", "http://searchyc.com/%s", $alternative = "http://news.ycombinator.com/");
define_webjump("stackoverflow",  "http://stackoverflow.com/search?q=%s", $alternative = "http://stackoverflow.com/");
define_webjump("superuser", "http://superuser.com/search?q=%s", $alternative = "http://superuser.com/");
#+END_SRC

*** Emacs
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("emacswiki",
   "http://www.google.com/cse?cx=004774160799092323420%3A6-ff2s0o6yi"+
       "&q=%s&sa=Search&siteurl=emacswiki.org%2F",
   $alternative="http://www.emacswiki.org/"); // emacswiki

define_webjump("marmalade", "http://marmalade-repo.org/packages?q=%s"); // emacs marmalade repo
#+END_SRC

*** Yandex
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("yandex", "http://yandex.com/yandsearch?text=%s"); // text
define_webjump("yandex.ru", "https://yandex.ru/yandsearch?text=%s"); // text ru
define_webjump("yimages", "http://images.yandex.com/yandsearch?text=%s"); // images
define_webjump("yimagesru", "http://images.yandex.ru/yandsearch?text=%s"); // images ru
define_webjump("ytrans", "http://translate.yandex.com/?lang=en-es&text=%s"); // translate en -> es
#+END_SRC

*** Kaldata
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("kaldata",
    "http://www.kaldata.com/forums/index.php?app=core&module=search&do=search&fromMainBar=1&search_term=%s");
#+END_SRC

*** Distrowatch (Search Distributions)
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("distrowatch", "http://distrowatch.com/table.php?distribution=%s");
#+END_SRC

*** DuckDuckGo
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("ddg", "http://duckduckgo.com/?q=%s");
#+END_SRC

*** Google
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("trans", "http://translate.google.com/translate_t#auto|en|%s");
define_webjump("imagesgoogle", "http://www.google.com/images?q=%s", $alternative = "http://www.google.com/imghp");
#+END_SRC

*** Popular
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("wordpress", "http://wordpress.org/search/%s");
define_webjump("youtube", "http://www.youtube.com/results?search_query=%s&search=Search");
define_webjump("deviantart", "http://browse.deviantart.com/?q=%s", $alternative="http://www.deviantart.com");
define_webjump("flickr", "http://www.flickr.com/search/?q=%s", $alternative="http://www.flickr.com");
#+END_SRC

*** GIT
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("github", "http://github.com/search?q=%s&type=Everything");
define_webjump("savannah", "https://savannah.gnu.org/search/?words=%s&type_of_search=soft");
define_webjump("gitorious", "http://gitorious.org/search?q=%s");
#+END_SRC

*** Wikipedia
#+BEGIN_SRC js :tangle ~/.conkerorrc
require("page-modes/wikipedia.js");
wikipedia_webjumps_format = "wp-%s"; // controls the names of the webjumps.  default is "wikipedia-%s".
define_wikipedia_webjumps("en", "es", "bg"); // For English, Spain and Bulgarian.
#+END_SRC

*** Ebay
#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("ebay", "http://search.ebay.es/search/search.dll?query=%s");
#+END_SRC

*** Lingvo

#+BEGIN_SRC js :tangle ~/.conkerorrc
define_webjump("lingvo", "http://www.lingvo-online.ru/en/Translate/en-es/%s");
#+END_SRC

*** Remove unused webjumps
#+BEGIN_SRC js :tangle ~/.conkerorrc
var unused_webjumps = ['answers', 'buildd','buildd-ports','clhs','cliki','clusty','creativecommons','debbugs','debfile','debpkg','debpopcon','debpts','debqa','freshmeat','kuro5hin','launchpad','lucky','ratpoisonwiki','sadelicious','scholar','sdelicious','slashdot','sourceforge','stumpwmwiki','ubuntubugs','ubuntufile','ubuntupkg','wiktionary','yahoo'];

for (var i=0; i<unused_webjumps.length; i++) {
    delete webjumps[unused_webjumps[i]];
}
#+END_SRC

** Keyboard

*** Caps Lock

Override the state of caps lock for command bindings, and force typed characters
to upper-case or lower-case based on whether shift was pressed with the character.

#+BEGIN_SRC js :tangle ~/.conkerorrc
key_bindings_ignore_capslock = true;
#+END_SRC

*** Disable the arrow keys in conkeror (use Emacs alternatives instead).

#+BEGIN_SRC js :tangle ~/.conkerorrc
undefine_key(content_buffer_normal_keymap, "up", "cmd_scrollLineUp");
undefine_key(content_buffer_normal_keymap, "down", "cmd_scrollLineDown");
undefine_key(content_buffer_normal_keymap, "left", "cmd_scrollLeft");
undefine_key(content_buffer_normal_keymap, "right", "cmd_scrollRight");
#+END_SRC

*** Enable eye-guide scrolling

#+BEGIN_SRC js :tangle ~/.conkerorrc
require('eye-guide.js');
define_key(content_buffer_normal_keymap, "space", "eye-guide-scroll-down");
define_key(content_buffer_normal_keymap, "back_space", "eye-guide-scroll-up");
#+END_SRC

** Functions
*** Disable gif animation on startup.

For some reasons I have disabled the gif animation on startup.

#+BEGIN_SRC js :tangle ~/.conkerorrc
session_pref("image.animation_mode", "none");
#+END_SRC

I have a simple function to enable gif animation with =f6= or typing =M-x enable-gif-animation=.

#+BEGIN_SRC js :tangle ~/.conkerorrc
interactive("enable-gif-animation",
    "Enable gif animation",
    function (I) {
       session_pref("image.animation_mode", "normal");
    });
define_key(default_global_keymap, "f6", "enable-gif-animation");
#+END_SRC

*** Conkeror goto-buffer.

#+BEGIN_SRC js :tangle ~/.conkerorrc
// - source http://puntoblogspot.blogspot.com.es/2013/08/conkeror-go-to-buffer.html
interactive("rgc-goto-buffer", "switches to buffer",
            function rgc_switch_to_buffer(I){
                var buff = yield I.minibuffer.read( $prompt = "number?:");
                switch_to_buffer(I.window, I.window.buffers.get_buffer(buff-1));
            }
);
define_key(content_buffer_normal_keymap, "M-g M-g", "rgc-goto-buffer");
#+END_SRC

*** Ask before closing the window.

#+BEGIN_SRC js :tangle ~/.conkerorrc
add_hook("window_before_close_hook",
         function () {
             var w = get_recent_conkeror_window();
             var result = (w == null) ||
                 "y" == (yield w.minibuffer.read_single_character_option(
                     $prompt = "Quit Conkeror? (y/n)",
                     $options = ["y", "n"]));
             yield co_return(result);
         });
#+END_SRC

*** Restore killed buffer Url.

#+BEGIN_SRC js :tangle ~/.conkerorrc
// I think by the time kill_buffer_hook runs the buffer is gone so I
// patch kill_buffer

var kill_buffer_original = kill_buffer_original || kill_buffer;

var killed_buffer_urls = [];

kill_buffer = function (buffer, force) {
    if (buffer.display_uri_string) {
        killed_buffer_urls.push(buffer.display_uri_string);
    }

    kill_buffer_original(buffer,force);
};

interactive("restore-killed-buffer-url", "Loads url from a previously killed buffer",
            function restore_killed_buffer_url (I) {
                if (killed_buffer_urls.length !== 0) {
                    var url = yield I.minibuffer.read(
                        $prompt = "Restore killed url:",
                        $completer = new all_word_completer($completions = killed_buffer_urls),
                        $default_completion = killed_buffer_urls[killed_buffer_urls.length - 1],
                        $auto_complete = "url",
                        $auto_complete_initial = true,
                        $auto_complete_delay = 0,
                        $require_match = true);

                    load_url_in_new_buffer(url);
                } else {
                    I.window.minibuffer.message("No killed buffer urls");
                }
            });
#+END_SRC

*** Clear conkeror history.

#+BEGIN_SRC js :tangle ~/.conkerorrc
function history_clear () {
    var history = Cc["@mozilla.org/browser/nav-history-service;1"]
        .getService(Ci.nsIBrowserHistory);
    history.removeAllPages();
}

interactive("history-clear",
            "Clear the history.",
            history_clear);
#+END_SRC

*** Start Hardcore radio.

#+BEGIN_SRC js :tangle ~/.conkerorrc
interactive("radio", "Start hardcore-radio", "follow-new-buffer",
           $browser_object = "http://www.hardcoreradio.nl/player/");
define_key(content_buffer_normal_keymap, "f1 r", "radio");
#+END_SRC

Go to the buffer that has radio (hardcore-radio).

#+BEGIN_SRC js :tangle ~/.conkerorrc
interactive("to-radio-buffer", "Shortcut to the buffer that has radio",
            function (I) {
                var buffers = I.window.buffers.buffer_list;
                for (i in buffers) {
                    if (buffers[i].current_uri.spec.substr(0, 35) ==
                        'http://www.hardcoreradio.nl/player/') {
                        switch_to_buffer(I.window, buffers[i]);
                        return;
                    }
                }
            });
define_key(content_buffer_normal_keymap, "C-x r", "to-radio-buffer");
#+END_SRC

*** User agent switcher.

#+BEGIN_SRC js :tangle ~/.conkerorrc
// source from https://github.com/technomancy/dotfiles/blob/master/.conkerorrc
var user_agents = { "conkeror": "Mozilla/5.0 (X11; Linux x86_64; rv:8.0.1) " +
                    "Gecko/20100101 conkeror/1.0pre",
                    "chromium": "Mozilla/5.0 (X11; U; Linux x86_64; en-US) " +
                    "AppleWebKit/534.3 (KHTML, like Gecko) Chrome/6.0.472.63" +
                    "Safari/534.3",
                    "firefox": "Mozilla/5.0 (X11; Linux x86_64; rv:8.0.1) " +
                    "Gecko/20100101 Firefox/8.0.1",
                    "android": "Mozilla/5.0 (Linux; U; Android 2.2; en-us; " +
                    "Nexus One Build/FRF91) AppleWebKit/533.1 (KHTML, like " +
                    "Gecko) Version/4.0 Mobile Safari/533.1"};
  var agent_completer = prefix_completer($completions = Object.keys(user_agents));
 interactive("user-agent", "Pick a user agent from the list of presets",
            function(I) {
                var ua = (yield I.window.minibuffer.read(
                    $prompt = "Agent:",
                    $completer = agent_completer));
                set_user_agent(user_agents[ua]);
            });
#+END_SRC


text:
#+TITLE: My .xinitrc file

#+ATTR_HTML: :alt xlogo.png image :title X :align left :width 480px :hight 280px
[[file:images/xlogo.png]]

** Enable DPMS energy saving.

When I want to disable the energy saving, I use a shell script to toggle =on|off= via ratpoison key bindings.
Get the script from [[https://raw2.github.com/ivoarch/bin/master/system/dpms-toggle.sh][here]].

#+begin_src sh :tangle ~/.xinitrc
xset +dpms; xset s on
#+end_src

** Enable killing Xorg.

By default, killing Xorg with the key combination Ctrl+Alt+Backspace is disabled.

#+begin_src sh :tangle ~/.xinitrc
setxkbmap -option terminate:ctrl_alt_bksp
#+end_src

** Configure the keyboard layout.

Switch between typing in English (us) and Bulgarian (bg) with =AltGr= key.

#+begin_src sh :tangle ~/.xinitrc
setxkbmap -layout us,bg -variant ,bas_phonetic -option grp:switch
#+end_src

** Adjusting keyboard and mouse speed.

I want to navigate faster so this is necessary.

#+begin_src sh :tangle ~/.xinitrc
xset r rate 200 50 &
xset m 3 1 &
#+end_src

Swap Left Control and Caps Lock.

#+BEGIN_SRC sh :tangle ~/.xinitrc
setxkbmap -option ctrl:swapcaps
#+END_SRC

** Set cursor theme

#+BEGIN_SRC sh :tangle ~/.xinitrc
xsetroot -cursor_name left_ptr
#+END_SRC
** Adding path to fonts.

#+begin_src sh :tangle ~/.xinitrc
xset +fp /usr/share/fonts/local
xset +fp /usr/share/fonts/TTF
xset +fp /usr/share/fonts/misc
xset fp rehash
#+end_src

** Load .Xresources

#+begin_src sh :tangle ~/.xinitrc
xrdb -merge ~/.Xresources
#+end_src

** Start Emacs as a daemon.

I want to have emacs running as a daemon on my system, and connect to the server using emacsclient.

#+begin_src sh :tangle ~/.xinitrc
emacs --daemon &
#+end_src

** Create and configure default desktop user directories.

#+BEGIN_SRC sh :tangle ~/.xinitrc
if [ -x /usr/bin/xdg-user-dirs-update ]; then
    /usr/bin/xdg-user-dirs-update
fi
#+END_SRC

** Start the RP window manager.

And finally, I start the window manager.

#+begin_src sh :tangle ~/.xinitrc
exec /usr/bin/ratpoison
#+end_src