├── Setup.hs ├── content ├── favicon.ico ├── profile.jpg ├── fonts │ ├── Aleo-Bold-webfont.eot │ ├── Aleo-Bold-webfont.ttf │ ├── Aleo-Bold-webfont.woff │ ├── Aleo-Regular-webfont.eot │ ├── Aleo-Regular-webfont.ttf │ └── Aleo-Regular-webfont.woff ├── index.html ├── images │ ├── encrypt-all-the-things.png │ ├── ml-2165-cups-test-page.jpg │ ├── success-kid-blurred-lines-ban.png │ └── screenshot-add-printer-over-lpd.png ├── robots.txt ├── cv.md └── mail@benjeffrey.com.asc ├── bower.json ├── src ├── deploy.sh ├── scss │ ├── code │ │ ├── _reset.scss │ │ ├── _syntax-highlighting-base.scss │ │ ├── _tron-legacy.scss │ │ └── _solarized-light.scss │ ├── _layout.scss │ ├── _foundation_settings.scss │ └── main.scss ├── nginx.conf ├── config.rb └── site.hs ├── templates ├── generic.html ├── post-list-item.html ├── post.html └── base.html ├── posts ├── 2014 │ └── 07 │ │ └── rinse-fm-unofficial-podcast-feed.md ├── 2015 │ └── 04 │ │ └── rinse-rss-update.md ├── useful-shell-commands.md ├── greasemonkey-script-for-wikipedia-subheading-links.md ├── screen.md ├── pitchpatch-wins-jisc-grant.md ├── quick-n-dirty-git-deployment.md ├── ml2165w-on-ubuntu.md ├── jane-street-interview-reparations.md ├── nginx.md ├── symbols.md ├── linux-processes.md ├── pandoc-syntax-highlighting-css.md ├── why-eusa-was-right-to-ban-blurred-lines.md ├── agreement-wall.md ├── ckan-ansible-playbook.md ├── setting-up-gandi-ssl-on-nginx.md └── building-benjeffrey.com-with-hakyll.md ├── .gitignore ├── README.md ├── benjeffrey-com.cabal └── LICENSE /Setup.hs: -------------------------------------------------------------------------------- 1 | import Distribution.Simple 2 | main = defaultMain 3 | -------------------------------------------------------------------------------- /content/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/favicon.ico -------------------------------------------------------------------------------- /content/profile.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/profile.jpg -------------------------------------------------------------------------------- /content/fonts/Aleo-Bold-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Bold-webfont.eot -------------------------------------------------------------------------------- /content/fonts/Aleo-Bold-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Bold-webfont.ttf -------------------------------------------------------------------------------- /content/fonts/Aleo-Bold-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Bold-webfont.woff -------------------------------------------------------------------------------- /content/fonts/Aleo-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Regular-webfont.eot -------------------------------------------------------------------------------- /content/fonts/Aleo-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Regular-webfont.ttf -------------------------------------------------------------------------------- /content/index.html: -------------------------------------------------------------------------------- 1 | --- 2 | title: ~Ben Jeffrey/ 3 | description: Informatics student, software developer, etc. 4 | --- 5 | $posts$ 6 | -------------------------------------------------------------------------------- /content/fonts/Aleo-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/fonts/Aleo-Regular-webfont.woff -------------------------------------------------------------------------------- /content/images/encrypt-all-the-things.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/images/encrypt-all-the-things.png -------------------------------------------------------------------------------- /content/images/ml-2165-cups-test-page.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/images/ml-2165-cups-test-page.jpg -------------------------------------------------------------------------------- /bower.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "benjeffrey.com", 3 | "dependencies": { 4 | "foundation": "~5.5.2", 5 | "foundation-icon-fonts": "*" 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /content/images/success-kid-blurred-lines-ban.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/images/success-kid-blurred-lines-ban.png -------------------------------------------------------------------------------- /content/robots.txt: -------------------------------------------------------------------------------- 1 | # www.robotstxt.org/ 2 | # www.google.com/support/webmasters/bin/answer.py?hl=en&answer=156449 3 | 4 | User-agent: * 5 | Disallow: 6 | -------------------------------------------------------------------------------- /content/images/screenshot-add-printer-over-lpd.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/jeffbr13/benjeffrey.com/master/content/images/screenshot-add-printer-over-lpd.png -------------------------------------------------------------------------------- /src/deploy.sh: -------------------------------------------------------------------------------- 1 | # sync compiled HTML 2 | rsync -aze ssh _site/ parsley:/var/www/benjeffrey.com/ 3 | # sync Nginx configuration 4 | rsync -aze ssh src/nginx.conf parsley:/etc/nginx/sites_enabled/benjeffrey.com 5 | -------------------------------------------------------------------------------- /templates/generic.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

$title$

4 |
5 | 6 |
7 | $body$ 8 |
9 | 10 |
11 | -------------------------------------------------------------------------------- /posts/useful-shell-commands.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Useful Shell Commands 3 | description: A collection of useful Linux shell commands 4 | date: 2013-04-16 5 | --- 6 | 7 | command description 8 | ------- ----------- 9 | `w` Show who is logged on and what they are doing. 10 | -------------------------------------------------------------------------------- /src/scss/code/_reset.scss: -------------------------------------------------------------------------------- 1 | pre { 2 | margin-bottom: 1em; 3 | padding: 1em; 4 | 5 | overflow-wrap: normal; 6 | overflow: auto; 7 | overflow-x: scroll; 8 | white-space: pre; 9 | } 10 | 11 | pre { 12 | code { 13 | background-color: inherit; 14 | border: inherit; 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | dist 2 | cabal-dev 3 | *.o 4 | *.hi 5 | *.chi 6 | *.chs.h 7 | .virthualenv 8 | 9 | # site compilation caches (Hakyll/Sass): 10 | _cache 11 | _site 12 | site 13 | hakyll 14 | generate-site 15 | src/.sass-cache 16 | 17 | # compiled CSS 18 | css 19 | 20 | # Cabal 21 | cabal.sandbox.config 22 | .cabal-sandbox 23 | 24 | # Bower components 25 | bower_components 26 | -------------------------------------------------------------------------------- /templates/post-list-item.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

$title$

4 |
5 | $if(description)$ 6 |
$description$
7 | $endif$ 8 |
$date$
9 |
10 |
11 |
12 | -------------------------------------------------------------------------------- /templates/post.html: -------------------------------------------------------------------------------- 1 |
2 |
3 |

$title$

4 |
5 | $if(description)$ 6 |
$description$
7 | $endif$ 8 |
$date$
9 |
10 |
11 | 12 |
13 | $body$ 14 |
15 |
16 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | benjeffrey.com 2 | ============== 3 | 4 | ```sh 5 | gem install sass compass 6 | bower update 7 | cabal update 8 | cabal sandbox init 9 | cabal install --only-dependencies 10 | ghc --make site.hs 11 | ``` 12 | 13 | ## Commands 14 | 15 | ```sh 16 | cabal build # compile executable 17 | dist/build/benjeffrey-com/benjeffrey-com build # build site 18 | dist/build/benjeffrey-com/benjeffrey-com rebuild # delete site and rebuild 19 | dist/build/benjeffrey-com/benjeffrey-com deploy # run src/deploy.sh 20 | ``` 21 | -------------------------------------------------------------------------------- /src/scss/code/_syntax-highlighting-base.scss: -------------------------------------------------------------------------------- 1 | // taken from https://raw.github.com/jaspervdj/hakyll/master/web/css/syntax.css 2 | // These tokens are marked up in Pandoc by the `highlighting-kate` package 3 | 4 | code { 5 | border: none; 6 | } 7 | 8 | pre { 9 | code { 10 | background-color: inherit; 11 | border: inherit; 12 | } 13 | } 14 | 15 | table.sourceCode, tr.sourceCode, td.lineNumbers, td.sourceCode, table.sourceCode pre { 16 | margin: 0; 17 | padding: 0; 18 | border: 0; 19 | vertical-align: baseline; 20 | border: none; 21 | } 22 | 23 | td.lineNumbers { 24 | border-right: 1px solid #AAAAAA; 25 | text-align: right; 26 | color: #AAAAAA; 27 | padding-right: 5px; 28 | padding-left: 5px; 29 | } 30 | 31 | 32 | td.sourceCode { 33 | padding-left: 5px; 34 | } 35 | -------------------------------------------------------------------------------- /src/nginx.conf: -------------------------------------------------------------------------------- 1 | # Nginx server configuration for benjeffrey.com 2 | 3 | # http://benjeffrey.com/* 4 | server { 5 | server_name benjeffrey.com; 6 | root /var/www/benjeffrey.com; 7 | 8 | listen 80; 9 | 10 | location / { 11 | index index.html index.htm index; 12 | try_files $uri $uri/ $uri.html =404; 13 | } 14 | } 15 | 16 | # redirect *.benjeffrey.net/.com to benjeffrey.com 17 | server { 18 | server_name *.benjeffrey.net *.benjeffrey.com; 19 | return 301 http://benjeffrey.com$request_uri; 20 | } 21 | 22 | # redirect https://benjeffrey.com to plain ol' HTTP 23 | server { 24 | server_name benjeffrey.com; 25 | listen 443 ssl; 26 | return 301 http://benjeffrey.com$request_uri; 27 | } 28 | -------------------------------------------------------------------------------- /src/scss/_layout.scss: -------------------------------------------------------------------------------- 1 | // Specify layout using the Foundation Grid Sass classes: 2 | //======================================================= 3 | 4 | .nav-wrapper { 5 | @include grid-row(); 6 | } 7 | .nav-wrapper > * { 8 | @include grid-column(12); 9 | } 10 | nav { 11 | margin-bottom: 1em; 12 | } 13 | 14 | article { 15 | @include grid-row(); 16 | 17 | header { 18 | .meta { 19 | margin-bottom: 1em; 20 | } 21 | } 22 | } 23 | article > * { 24 | @include grid-column(12); 25 | } 26 | 27 | // Footer: 28 | //-------- 29 | 30 | @import "compass/layout/sticky-footer"; 31 | @include sticky-footer(7em, ".wrapper", ".push", "footer"); 32 | 33 | footer { 34 | padding-top: 3em; 35 | 36 | p { 37 | text-align: center; 38 | max-width: none; 39 | } 40 | } 41 | 42 | .push { 43 | margin-top: 6em; 44 | } 45 | -------------------------------------------------------------------------------- /src/scss/code/_tron-legacy.scss: -------------------------------------------------------------------------------- 1 | // Colour scheme based on Dayle Rees's TronLegacy color-scheme 2 | // https://github.com/daylerees/colour-schemes 3 | // http://tmtheme-editor.herokuapp.com/ 4 | // http://hackage.haskell.org/package/highlighting-kate 5 | @import "syntax-highlighting-base"; 6 | 7 | $background: #14191F; 8 | $foreground: #AEC2E0; 9 | $comment: #324357; 10 | $string: #FF410D; 11 | $number: #C7F026; 12 | $keyword: #748AA6; 13 | 14 | 15 | .sourceCode, code { 16 | background-color: $background; 17 | color: $foreground; 18 | 19 | .kw { color: $keyword; } 20 | .bn { color: $number; } 21 | .fl { color: $number; } 22 | .ch { color: $string; } 23 | .st { color: $string; } 24 | .co { color: $comment; } 25 | .ot { color: #A57800; } 26 | .al { color: #CB4B16; font-weight: bold; } 27 | .fu { color: $keyword; } 28 | .er { color: #D30102; font-weight: bold; } 29 | } 30 | -------------------------------------------------------------------------------- /benjeffrey-com.cabal: -------------------------------------------------------------------------------- 1 | -- Initial benjeffrey-com.cabal generated by cabal init. For further 2 | -- documentation, see http://haskell.org/cabal/users-guide/ 3 | 4 | name: benjeffrey-com 5 | version: 0.1.0 6 | synopsis: Ben Jeffrey's personal webpage 7 | -- description: 8 | homepage: https://benjeffrey.com 9 | license: MPL-2.0 10 | license-file: LICENSE 11 | author: Ben Jeffrey 12 | maintainer: mail@benjeffrey.net 13 | -- copyright: 14 | category: Web 15 | build-type: Simple 16 | extra-source-files: README.md 17 | cabal-version: >=1.10 18 | 19 | executable benjeffrey-com 20 | main-is: Site.hs 21 | ghc-options: -Wall 22 | -- other-modules: 23 | -- other-extensions: 24 | build-depends: base >=4.8 && <4.9, 25 | hakyll, 26 | pandoc 27 | hs-source-dirs: src 28 | default-language: Haskell2010 29 | -------------------------------------------------------------------------------- /src/config.rb: -------------------------------------------------------------------------------- 1 | # Require any additional compass plugins here. 2 | require "zurb-foundation" 3 | 4 | # Set this to the root of your project when deployed: 5 | http_path = "/" 6 | css_dir = "css" 7 | sass_dir = "scss" 8 | images_dir = "images" 9 | javascripts_dir = "js" 10 | 11 | # You can select your preferred output style here (can be overridden via the command line): 12 | # output_style = :expanded or :nested or :compact or :compressed 13 | output_style = :compressed 14 | 15 | # To enable relative paths to assets via compass helper functions. Uncomment: 16 | # relative_assets = true 17 | 18 | # To disable debugging comments that display the original location of your selectors. Uncomment: 19 | line_comments = false 20 | 21 | 22 | # If you prefer the indented syntax, you might want to regenerate this 23 | # project again passing --syntax sass, or you can uncomment this: 24 | # preferred_syntax = :sass 25 | # and then run: 26 | # sass-convert -R --from scss --to sass scss scss && rm -rf sass && mv scss sass 27 | -------------------------------------------------------------------------------- /posts/2015/04/rinse-rss-update.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: An Update to rinse-rss 3 | date: 2015-04-13 4 | --- 5 | 6 | Banger banger banger! I’m happy to announce that I’ve finally updated [`rinse-rss`](http://rinse.benjeffrey.net "Rinse FM unofficial podcast feed"), my unofficial RSS feed generator for [Rinse FM](http://rinse.fm), to version `0.3.2-beezledub`, and you can now subscribe to recurring show-feeds without them dying on you later in the week! 7 | 8 | [Riiiiiiiiiiiinse...](http://rinse.benjeffrey.net "Rinse FM unofficial podcast feed") 9 | 10 | 11 | ## Technical Details 12 | 13 | - a separate [Celery](http://www.celeryproject.org) worker asynchronously scrapes Rinse FM every so-often, rather than it happening during HTTP request processing 14 | - the scraped data is now stored in Postgres using [SQLAlchemy](http://www.sqlalchemy.org) 15 | - everything is containerised, and run using [Docker Compose](http://docs.docker.com/compose/) 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /posts/2014/07/rinse-fm-unofficial-podcast-feed.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Rinse FM unofficial podcast feed 3 | date: 2014-07-01 4 | tags: project 5 | --- 6 | 7 | [Rinse FM](http://rinse.fm/)'s website CMS doesn't enclose the podcast media files in it's podcast RSS feeds, making it impossible to subscribe with podcatchers. 8 | 9 | I was using [\@levelsio's Rinse FM podcast](https://levels.io/rinse-fm-podcast/) with great success for a long time. Unfortunately, it seems to break whenever there's a format-change or any erroneous data-entry on Rinse FM's side. I've [tweeted \@levelsio when it's broken in the past](https://twitter.com/jeffbr13/status/447019136934486016), but it seems unfair to bug him to keep it maintained, and he's not open-sourced it yet so I can't go in and fix the software myself. 10 | 11 | So I built my own unofficial Rinse FM podcast feed! I built it with Python 3 and Flask, it's open-source under [the Mozilla Public License (2.0)](https://www.mozilla.org/MPL/2.0/), and the feeds are available at . Enjoy! 12 | 13 | - [Rinse FM unofficial podcast feed](http://rinse.benjeffrey.net) 14 | - [rinse-rss source code](https://github.com/jeffbr13/rinse-rss) 15 | -------------------------------------------------------------------------------- /src/scss/code/_solarized-light.scss: -------------------------------------------------------------------------------- 1 | @import "syntax-highlighting-base"; 2 | 3 | // Solarized's colour pallete. 4 | $base03: #002B36; 5 | $base02: #073642; 6 | $base01: #586E75; 7 | $base00: #657B83; 8 | $base0: #839496; 9 | $base1: #93A1A1; 10 | $base2: #EEE8D5; 11 | $base3: #FDF6E3; 12 | $yellow: #B58900; 13 | $orange: #CB4B16; 14 | $red: #DC322F; 15 | $magenta: #D33682; 16 | $violet: #6C71C4; 17 | $blue: #268BD2; 18 | $cyan: #2AA198; 19 | $green: #859900; 20 | 21 | 22 | pre, code { 23 | background-color: $base3; 24 | } 25 | 26 | .sourceCode { 27 | // KeyWordTok 28 | .kw { color: $blue; } 29 | // DataTypeTok 30 | .dt { color: $blue; } 31 | // DecValTok (decimal value), BaseNTok, FloatTok 32 | .dv, .bn, .fl { color: $magenta; } 33 | // CharTok 34 | .ch { color: $red; } 35 | // StringTok 36 | .st { color: $cyan; } 37 | // CommentTok 38 | .co { color: $base1; } 39 | // OtherTok 40 | .ot { color: $yellow; } 41 | // AlertTok 42 | .al { color: $orange; font-weight: bold; } 43 | // FunctionTok 44 | .fu { color: $blue; } 45 | // RegionMarkerTok 46 | .re { } 47 | // ErrorTok 48 | .er { color: $red; font-weight: bold; } 49 | } 50 | -------------------------------------------------------------------------------- /src/scss/_foundation_settings.scss: -------------------------------------------------------------------------------- 1 | // Allows the use of rem-calc() or lower-bound() in your settings 2 | @import '../../bower_components/foundation/scss/foundation/functions'; 3 | 4 | // The default font-size is set to 100% of the browser style sheet (usually 16px) 5 | // for compatibility with browser-based text zoom or user-set defaults. 6 | 7 | // Since the typical default browser font-size is 16px, that makes the calculation for grid size. 8 | // If you want your base font-size to be different and not have it affect the grid breakpoints, 9 | // set $rem-base to $base-font-size and make sure $base-font-size is a px value. 10 | $base-font-size: 15px; 11 | 12 | // We use this to control whether or not CSS classes come through in the gem files. 13 | $include-html-classes: true; 14 | // $include-print-styles: true; 15 | $include-html-global-classes: $include-html-classes; 16 | 17 | // We use these to define default font stacks 18 | // $font-family-sans-serif: "Helvetica Neue", Helvetica, Roboto, Arial, sans-serif; 19 | $font-family-serif: "Merriweather", "DejaVu Serif", serif; 20 | $font-family-monospace: 'Source Code Pro', Consolas, 'DejaVu Sans Mono', monospace;; 21 | 22 | 23 | // We use these as default colors throughout 24 | $primary-color: rgb(208,67,60); 25 | $secondary-color: rgb(52,73,94); 26 | // $alert-color: #f04124; 27 | // $success-color: #43AC6A; 28 | // $warning-color: #f08a24; 29 | // $info-color: #a0d3e8; 30 | 31 | $body-font-family: $font-family-serif; 32 | 33 | $header-font-family: "Aleo", "Roboto Slab", "DejaVu Serif", sans-serif; 34 | 35 | $list-style-position: inside; 36 | -------------------------------------------------------------------------------- /posts/greasemonkey-script-for-wikipedia-subheading-links.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Greasemonkey script to add link anchors to Wikipedia page subheadings 3 | date: 2014-04-29 4 | --- 5 | 6 | Linking to specific sections of a Wikipedia article can be mildly annoying, requiring you to either 7 | 8 | A) inspect the page source and find the subsection heading's `id` attribute, or 9 | B) scroll back up to the TOC and get the link from there. 10 | 11 | Instead, in the spirit of hacker laziness, here's a Greasemonkey script which wraps Wikipedia page subsection headings in links: 12 | 13 | ```javascript 14 | // https://benjeffrey.com/greasemonkey-script-for-wikipedia-subheading-links 15 | // Available under the MPL 2.0 16 | // ==UserScript== 17 | // @key value 18 | // @name Wikipedia Subheading Links 19 | // @namespace com.benjeffrey.wikipedia-subheading-links 20 | // @description Add links to subheadings on Wikipedia pages. 21 | // @include http://*.wikipedia.org/* 22 | // @include https://*.wikipedia.org/* 23 | // ==/UserScript== 24 | contentsItems = document.getElementById('toc').getElementsByTagName('li'); 25 | for (var i = 0; i < contentsItems.length; i++) { 26 | subheadingHash = contentsItems[i].getElementsByTagName('a')[0].hash.slice(1); 27 | subheading = document.getElementById(subheadingHash); 28 | subheading.innerHTML = ('' + subheading.innerHTML + ' #'); 29 | } 30 | ``` 31 | 32 | Apologies for the *ahem* MVP-like quality of the JavaScript... 33 | 34 | [Greasemonkey script to add link anchors to Wikipedia page subheadings (Gist)](https://gist.github.com/jeffbr13/11387443). 35 | -------------------------------------------------------------------------------- /posts/screen.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: screen 3 | description: Some notes on using the screen shell session software 4 | date: 2012-10-26 5 | ----- 6 | 7 | `screen` is a useful and powerful program that allows you to create and 8 | manage multiple virtual sessions, independently of how or where you're 9 | logged into a machine. 10 | 11 | 12 | Running a Screen session 13 | ------------------------ 14 | 15 | To create a screen session, simply type `screen` and you will get a splash 16 | screen (at which you press space). 17 | 18 | Whilst in screen, your terminal will not beep, but instead will flash 19 | visually when it receives a beep command from an application. 20 | 21 | Recovering sessions 22 | ------------------- 23 | 24 | If you lose (or detach from) a single `screen` session, you can bring it 25 | back up with: 26 | 27 | ```bash 28 | screen -r 29 | ``` 30 | 31 | If you had multiple `screen` sessions running, this command will bring up a list 32 | of them. 33 | 34 | ### Naming sessions 35 | You can name `screen` sessions to keep track of them: 36 | 37 | ```bash 38 | screen -S [my session] 39 | ``` 40 | 41 | 42 | Detaching from Screen sessions 43 | ------------------------------ 44 | 45 | You can detach yourself from a running `screen` session via the key-command 46 | ctrl-a-d. 47 | 48 | To reattach a session (the `-d` switch detaches the session from other 49 | terminals, if necessary): 50 | 51 | ```bash 52 | screen -rd [my session] 53 | ``` 54 | 55 | or alternatively 56 | 57 | ```bash 58 | screen -rx [another session] 59 | ``` 60 | 61 | which will allow you to attach to a screen session without detaching it from 62 | any other terminals - multi-screen mode! 63 | -------------------------------------------------------------------------------- /posts/pitchpatch-wins-jisc-grant.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: Pitchpatch wins JISC grant 3 | description: Thanks everyone! Now, to build the damned thing... 4 | date: 2013-07-01 5 | ----- 6 | 7 | I just want to say thanks to everyone who voted for us in Jisc's 8 | ["Summer of Student Innovation"][sosi] competition! Caroline and myself 9 | *literally* couldn't have done it without you. 10 | 11 | By the end of July 12 | the University of Edinburgh will receive (and begin distributing) the 13 | Elevator Fund grant money to us. 14 | However, we're already starting work on [Pitchpatch][] in 15 | earnest, and thinking up ways to ~~blow all this spending money~~ make the 16 | best use of 17 | these newly-acquired resources! 18 | 19 | We're [one of 21 winners][winners] from a total of 36 submitted ideas (so 20 | the field wasn't huge) but they were of a pretty high standard overall, 21 | with [one][goncode] or [two][wikinets] really piquing my attention. 22 | It was a pretty strong result for a competition aiming to stimulating innovation 23 | inside of universities, and I'm really looking forward to the results 24 | of all the other projects. 25 | 26 | As one of the prize's conditions we have to post our process frequently, 27 | so do follow our Pitchpatch adventure at [blog.pitchpatch.co][]! 28 | 29 | 30 | 31 | 32 | [sosi]: http://elevator.jisc.ac.uk/ 33 | [goncode]: http://www.youtube.com/watch?v=4Kq5K_xnmek 34 | [wikinets]: http://www.youtube.com/watch?v=ozc2vKfvCzc 35 | [winners]: http://www.jisc.ac.uk/blog/the-summer-of-student-innovation-winners-announced-01-jul-2013 36 | [JISC]: http://jisc.ac.uk/ 37 | [Pitchpatch]: http://pitchpatch.co/ 38 | [blog.pitchpatch.co]: http://blog.pitchpatch.co/ 39 | -------------------------------------------------------------------------------- /src/scss/main.scss: -------------------------------------------------------------------------------- 1 | $fi-path: "./fonts"; 2 | 3 | @import "foundation_settings"; 4 | @import "../../bower_components/foundation/scss/foundation.scss"; 5 | @import "../../bower_components/foundation-icon-fonts/foundation-icons"; 6 | @import "layout"; 7 | @import "code/solarized-light"; 8 | 9 | // Typography: 10 | //------------ 11 | @import url(https://fonts.googleapis.com/css?family=Merriweather:300,300italic,700|Source+Code+Pro); 12 | 13 | @font-face { 14 | font-family: 'Aleo'; 15 | src: url('/fonts/Aleo-Bold-webfont.eot'); 16 | src: url('/fonts/Aleo-Bold-webfont.eot?#iefix') format('embedded-opentype'), 17 | url('/fonts/Aleo-Bold-webfont.woff') format('woff'), 18 | url('/fonts/Aleo-Bold-webfont.ttf') format('truetype'), 19 | url('/fonts/Aleo-Bold-webfont.svg#aleobold') format('svg'); 20 | font-weight: bold; 21 | font-style: normal; 22 | 23 | } 24 | @font-face { 25 | font-family: 'Aleo'; 26 | src: url('/fonts/Aleo-Regular-webfont.eot'); 27 | src: url('/fonts/Aleo-Regular-webfont.eot?#iefix') format('embedded-opentype'), 28 | url('/fonts/Aleo-Regular-webfont.woff') format('woff'), 29 | url('/fonts/Aleo-Regular-webfont.ttf') format('truetype'), 30 | url('/fonts/Aleo-Regular-webfont.svg#aleoregular') format('svg'); 31 | font-weight: normal; 32 | font-style: normal; 33 | 34 | } 35 | 36 | // Fading nav area 37 | //---------------- 38 | @import "compass/css3"; 39 | nav { 40 | opacity: 0.4; 41 | @media #{$small-only} { 42 | opacity: 1.0; 43 | } 44 | @include transition-property(opacity); 45 | @include transition-duration(0.5s); 46 | @include transition-timing-function(ease); 47 | 48 | &:active, 49 | &:focus, 50 | &:hover { 51 | opacity: 1.0; 52 | } 53 | } 54 | 55 | nav { 56 | background-color: rgba(0,0,0,0.12); 57 | border-bottom: solid 2em $primary-color; 58 | } 59 | 60 | 61 | // Blockquote citations to the right 62 | // --------------------------------- 63 | cite { 64 | display: block; 65 | text-align: right; 66 | } 67 | 68 | // Invisible heading links 69 | // ----------------------- 70 | h1, h2, h3, h4, h5 { 71 | a { 72 | color: inherit; 73 | text-decoration: none; 74 | } 75 | } 76 | 77 | .meta { 78 | color: $secondary-color; 79 | } 80 | -------------------------------------------------------------------------------- /posts/quick-n-dirty-git-deployment.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Quick 'n' Dirty Git Deployment 3 | description: A simple solution to deploy source code with remote tracking branches and post-receive hooks. 4 | date: 2013-08-17 5 | --- 6 | 7 | Git is a D-for-distributed DVCS, meaning that your repository doesn't need 8 | to live at any canonical location. 9 | It can reside entirely on each team-member's hard-drive, 10 | but it's generally a good idea to have a remote copy of your repository for 11 | both backup and collaboration purposes. 12 | 13 | If a remote location is all you need, then look into bare repositories, as they 14 | were designed for this. 15 | 16 | However, if you want a working directory with a copy of your code directly on 17 | the server, you'll need a setup more like the following. 18 | I'm pretty sure a post-receive hook and a bare repository would be 19 | a safer way to do this, but it works. 20 | 21 | 26 | 27 | 28 | ## 1: Copy repository to remote server 29 | 30 | Make sure your repository is neat, then copy the entire contents of the 31 | working directory to your remote server: 32 | 33 | ```bash 34 | scp -rC ./ user@server:/var/www/project 35 | ``` 36 | 37 | 38 | ## 2: Allow pushing to the remote repository 39 | 40 | If you try and push up to a remote repo normally, you get an annoying 41 | `Can't push to checked-out branch` error. To allow pushing to the currently 42 | checked-out branch, `cd` to the new repository+working directory on your 43 | remote server, and set the following flag: 44 | 45 | ```bash 46 | git config --bool receive.denyCurrentBranch false 47 | ``` 48 | 49 | 50 | ## 3: Create a post-receive hook to checkout pushed changes 51 | 52 | Git won't automatically re-checkout the branch you push to, so you'll need 53 | a fancy "post-receive hook" to update your working directory each time you push. 54 | 55 | Add the following lines to `.git/hooks/post-receive` in your remote repo: 56 | 57 | ```bash 58 | # Update working tree after receiving pushed branch 59 | echo "*****************************************************" 60 | echo "Post-receive hook: updating remote working directory" 61 | echo "*****************************************************" 62 | cd .. 63 | env -i git reset --hard 64 | ``` 65 | 66 | then set the executable bit on it: 67 | 68 | ```bash 69 | chmod +x .git/hooks/post-receive 70 | ``` 71 | 72 | 73 | ## 4: Set up remote tracking branches 74 | 75 | ```bash 76 | git remote add REMOTE-NAME user@server:/var/www/html/project 77 | git push REMOTE-NAME BRANCH 78 | ``` 79 | 80 | -------------------------------------------------------------------------------- /templates/base.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | $title$ 6 | $if(description)$ 7 | 8 | $endif$ 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 25 | 26 | 27 | 28 | 29 |
30 | 59 | 60 | $body$ 61 |
62 | 63 |
64 | 65 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /posts/ml2165w-on-ubuntu.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: Samsung ML-2165W Printer on Ubuntu Raring 3 | description: Setting up the Samsung ML-2165W wireless monochrome laser printer on Ubuntu 13.04 4 | date: 2013-05-08 5 | ----- 6 | 7 | I had a few problems getting my new wireless [ML-2165W][] monochrome laser- 8 | printer-thing set-up initially, but I eventually got it working with 9 | a clean install of Ubuntu 13.04 (Raring Ringtail). And---by gum---it's 10 | speedy for a cheap printer! 11 | 12 | The following piece records how I got my ML-2165W working. The 13 | intsructions here may not be complete, and probably won't work for you. 14 | After all *it's a printer*. If you have trouble, the best place to go is 15 | the [SULDR homepage](http://bchemnet.com/suldr/), and to start working 16 | your way through the limited literature from there. 17 | 18 | 19 | Add the SULDR 20 | --------------------------------------------------------------------------- 21 | 22 | The [SULDR](http://bchemnet.com/suldr/) handily repackages the official 23 | Samsung printer drivers, and was invaluable in getting my printer 24 | working -- Samsung printer drivers are found lacking with regards to 25 | installation on Linux systems. 26 | 27 | 28 | ```bash 29 | sudo bash -c 'echo "deb http://www.bchemnet.com/suldr/ debian extra" >> /etc/apt/sources.list' 30 | sudo wget -O - http://www.bchemnet.com/suldr/suldr.gpg | sudo apt-key add - 31 | sudo apt-get update 32 | ``` 33 | 34 | 35 | Install the Driver Package 36 | -------------------------- 37 | 38 | I selected the slightly older `suld-driver-4.00.39` package which seems 39 | to be the most direct route to a working ML-2160-series printer driver: 40 | 41 | ```bash 42 | sudo apt-get install suld-driver-4.00.39 43 | ``` 44 | 45 | 46 | Add the Printer to your Network 47 | ------------------------------- 48 | 49 | Use [WPS](http://en.wikipedia.org/wiki/Wi-Fi_Protected_Setup) to setup a 50 | connection between the printer and your router. Alternatively, find a 51 | Windows PC to run the included installation disc and configure the 52 | network using that. 53 | 54 | 55 | Configure the Network Printer 56 | ----------------------------- 57 | 58 | Then I added the printer through the Ubuntu "Printers" utility as an 59 | **[LPD Network 60 | Printer](http://en.wikipedia.org/wiki/Line_Printer_Daemon_protocol)** -- 61 | apparently [some Samsung printer/driver combinations can be buggy over 62 | IPP](http://www.bchemnet.com/suldr/forum/index.php?topic=87.0#msg_361). 63 | 64 | ![Ensure you add the printer using the LPD protocol.](../images/screenshot-add-printer-over-lpd.png) 65 | 66 | The ML-2165W should then detected as an ML-2160-series printer, after 67 | searching for drivers. 68 | 69 | 70 | Printing a Page 71 | --------------- 72 | 73 | 74 | I'm not entirely sure whether or not it helped, but I also sent a text 75 | file to the printer through `lp`, [which supposedly fixes common 76 | configuration 'blockages'](http://bchemnet.com/suldr/printing.html#12). 77 | The text file itself never printed, in my case: 78 | 79 | ```bash 80 | lp -d {printer} {text file} 81 | ``` 82 | 83 | ![Yay, it works! And yes it is past my bedtime.](../images/ml-2165-cups-test-page.jpg) 84 | 85 | Once the printer is fully configured, you should be able to print a CUPS 86 | test-page, as above! 87 | 88 | 89 | 90 | [ML-2165W]: http://www.samsung.com/hk_en/consumer/computer-peripherals/printers-multifunction/monochrome-laser-printers/ML-2165/XSS 91 | -------------------------------------------------------------------------------- /posts/jane-street-interview-reparations.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Jane Street Interview Reparations 3 | description: I messed up in a coding exercise. So here, have a functional Queue implementation in Haskell. 4 | date: 2013-10-18 5 | --- 6 | 7 | So today I had a telephone interview with the 'market makers' [Jane Street](http://janestreet.com/), for 8 | a summer internship position. They're a financial trading company 9 | who use ML as their main programming language and have not only [open-sourced](http://janestreet.github.io/) 10 | a complete asynchronous library, but also their own take on the OCaml standard 11 | library! So these guys obviously lean heavily to the functional side of the 12 | programming spectrum. 13 | 14 | So yeah, I should perhaps have prepared better for their call! 15 | The interviewer said that I could work in any language I wanted to, and my 16 | challenge would be to implement a queue. I chose 17 | Python as my weapon, as I had been using it at work just a little earlier 18 | in the day. 19 | 20 | This was a mistake. The first task was to come up with type signatures 21 | for the core queue functions, `push` and `pop`. And without any such thing 22 | existing in Python, I tried to lean on my rusty Haskell knowledge to come 23 | up with `push :: a -> Queue a -> Queue a` and `pop :: Queue a -> a -> Queue a`. 24 | An astute reader (or interviewer) familiar with this type notation will note that **both are wrong**. 25 | 26 | It only went (slightly) downhill from there. The following tasks [my 27 | mistakes in brackets] were to: 28 | 29 | - implement this queue *functionally* (i.e. returning the changed queue), using 2 lists to amortize lookup complexity 30 | [I decided to write this as a Python class... *hurr-durr*] 31 | - implement a `peek` function [I mostly just copypasted from my `Queue.pop` 32 | implementation] 33 | - ensure that the queue followed FIFO ordering [mine didn't at first!] 34 | 35 | To make up for these errors upon errors, here are a couple of functional 36 | queue implementations in Haskell: 37 | 38 | ```haskell 39 | -- Naïve implementation of a queue as a list, so pops are O(n) complexity. 40 | 41 | newtype Queue a = Queue [a] 42 | deriving (Show, Read) 43 | 44 | push :: a -> Queue a -> Queue a 45 | push x (Queue xs) = Queue (x:xs) 46 | 47 | pop :: Queue a -> (a, Queue a) 48 | pop (Queue xs) = (last xs, Queue (init xs)) 49 | 50 | peek :: Queue a -> (a, Queue a) 51 | peek (Queue xs) = (last xs, Queue xs) 52 | ``` 53 | 54 | The naïve implementation also doesn't handle empty lists, but it's getting to the wee hours of the morning now. 55 | I spent a little more time on my attempt which uses two lists to amortize complexity: 56 | 57 | ```haskell 58 | -- Two-list queue implementation, where: 59 | -- * pushes are cons'd to the front of the `in` list. 60 | -- * pops the head of the `out` list. 61 | -- * we reverse and set the `in` list as the `out` list if the `out` list is empty. 62 | 63 | data Queue a = Queue {in_l :: [a], 64 | out_l :: [a]} 65 | deriving (Eq, Read, Show) 66 | 67 | push :: a -> Queue a -> Queue a 68 | push x q -- (in) (out) 69 | | length (out_l q) == 0 = Queue ([]) ([x]) 70 | | otherwise = Queue (x:(in_l q)) (out_l q) 71 | 72 | pop :: Queue a -> (Maybe a, Queue a) 73 | pop (Queue [] []) = (Nothing, Queue [] []) 74 | pop (Queue xs []) = pop (Queue [] (reverse xs)) 75 | pop (Queue xs ys) = ((Just (head ys)), Queue xs (tail ys)) 76 | 77 | peek :: Queue a -> (Maybe a, Queue a) 78 | peek (Queue [] []) = (Nothing, Queue [] []) 79 | peek (Queue xs []) = peek (Queue [] (reverse xs)) 80 | peek (Queue xs ys) = ((Just (head ys)), Queue xs ys) 81 | ``` 82 | 83 | Further room for improvement? I could perhaps rewrite `pop` using `peek`, 84 | but *sleep*. 85 | -------------------------------------------------------------------------------- /posts/nginx.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: Basic Nginx configuration 3 | description: A few notes on how to configure Nginx, out of the box 4 | date: 2012-10-05 5 | ----- 6 | 7 | 8 | Installation 9 | ------------ 10 | 11 | You'll usually want to install Nginx from their stable repo, rather than 12 | the older (but more tested) versions in your distro's software 13 | repositories. 14 | 15 | ### Ubuntu 16 | 17 | Note that you may need to install the `python-software-properties` 18 | package in order to use the `add-apt-repository` command on your system. 19 | 20 | ```bash 21 | add-apt-repository ppa:nginx/stable 22 | apt-get update 23 | apt-get install nginx 24 | ``` 25 | 26 | ### CentOS 6 27 | 28 | There is an `nginx-release` RPM package available on the [Nginx 29 | website](http://nginx.org/en/download.html), which will configure `yum` 30 | with the repositories needed to install Nginx. For CentOS 6 in 31 | particular, you can run the following commands: 32 | 33 | ```bash 34 | wget http://nginx.org/packages/centos/6/noarch/RPMS/nginx-release-centos-6-0.el6.ngx.noarch.rpm 35 | yum install ./nginx-release-centos-6-0.el6.ngx.noarch.rpm 36 | yum install nginx 37 | ``` 38 | 39 | 40 | Configuration 41 | ------------- 42 | 43 | The main configuration file is located at `/etc/nginx/nginx.conf`, 44 | while the default site configuration is usually to be found in either of: 45 | 46 | * `/etc/nginx/conf.d/default.conf` 47 | * `/etc/nginx/sites-available/default` 48 | 49 | The default document root on Ubuntu is `/usr/share/nginx/www`. 50 | 51 | A few extra options are always handy set: 52 | 53 | ### Worker Processes 54 | 55 | Helps to ensure that the server doesn't get bogged down by a single 56 | client, as the server calculates `max_clients` as `worker_processes` ✕ 57 | `worker_connections` Let's use those cores to their full advantage! 58 | 59 | worker_processes 4; 60 | 61 | 62 | ### Turn on [Gzip][] compression 63 | 64 | ```conf 65 | gzip on; 66 | # IE6 can't handle Gzip[!] 67 | gzip_disable "msie6"; 68 | # Allow gzipping responses to proxy requests 69 | gzip_proxied any; 70 | # Tell Nginx to gzip the following filetypes 71 | gzip_types text/plain text/html text/css application/x-javascript text/xml application/xml application/xml+rss text/javascript; 72 | ``` 73 | 74 | 75 | Virtual Servers 76 | --------------- 77 | 78 | [When Nginx processes a request](http://nginx.org/en/docs/http/request_processing.html), 79 | it checks which virtual server should process it. 80 | 81 | Server configurations are defined and kept in two locations: 82 | 83 | /etc/nginx/sites-available 84 | /etc/nginx/sites-enabled 85 | 86 | The first holds the actual configuration files, which you link to from 87 | the `sites-enabled` directory. This layout allows adding or removing 88 | virtually hosted sites from Nginx at will, without even touching the 89 | configuration files. 90 | 91 | ### Document Root 92 | 93 | You'll need to creat `/var/www/`: 94 | 95 | ```bash 96 | mkdir -p /var/www/ 97 | ``` 98 | 99 | Uncomment both `listen` lines to make Nginx listen on port 80 IPv4 and IPv6. 100 | `server_name _;` is an invalid directive, making this a default catchall vhost 101 | of course, you can as well specify a hostname here like www.example.com). 102 | 103 | Now save the file and restart nginx: 104 | 105 | ```bash 106 | /etc/init.d/nginx restart 107 | ``` 108 | 109 | Enable the vhost and reload Nginx: 110 | 111 | ```bash 112 | cd /etc/nginx/sites-enabled/ 113 | ln -s /etc/nginx/sites-available/www.hostmauritius.com 114 | /etc/init.d/nginx reload 115 | ``` 116 | 117 | 118 | Sources 119 | ---------------------------------------- 120 | 121 | * 122 | * 123 | * 124 | 125 | 126 | 127 | 128 | 129 | [Gzip]: https://en.wikipedia.org/wiki/Gzip 130 | -------------------------------------------------------------------------------- /src/site.hs: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- 2 | {-# LANGUAGE OverloadedStrings #-} 3 | import Hakyll 4 | import qualified Text.Pandoc.Options as Pandoc.Options 5 | 6 | 7 | -------------------------------------------------------------------------------- 8 | config :: Configuration 9 | config = defaultConfiguration 10 | { deployCommand = "src/deploy.sh"} 11 | 12 | pandocWriterOptions :: Pandoc.Options.WriterOptions 13 | pandocWriterOptions = defaultHakyllWriterOptions 14 | { Pandoc.Options.writerHtml5 = True 15 | , Pandoc.Options.writerHtmlQTags = True 16 | --, Pandoc.Options.writerNumberSections = True 17 | --, Pandoc.Options.writerNumberOffset = [1] 18 | , Pandoc.Options.writerSectionDivs = True 19 | , Pandoc.Options.writerTableOfContents = True 20 | } 21 | 22 | postsDirectory :: Pattern 23 | postsDirectory = "posts/**" 24 | -------------------------------------------------------------------------------- 25 | main :: IO () 26 | main = hakyllWith config $ do 27 | 28 | match "templates/*" $ compile templateCompiler 29 | 30 | 31 | -- compile CV: 32 | match (fromList ["content/cv.md"]) $ do 33 | route $ setExtension "" `composeRoutes` gsubRoute "content/" (const "") 34 | compile $ pandocCompilerWith defaultHakyllReaderOptions pandocWriterOptions 35 | >>= loadAndApplyTemplate "templates/generic.html" defaultContext 36 | >>= loadAndApplyTemplate "templates/base.html" defaultContext 37 | >>= relativizeUrls 38 | 39 | 40 | -- compile posts: 41 | match postsDirectory $ do 42 | route $ setExtension "" `composeRoutes` gsubRoute "content/" (const "") 43 | compile $ pandocCompilerWith defaultHakyllReaderOptions pandocWriterOptions 44 | >>= loadAndApplyTemplate "templates/post.html" postCtx 45 | >>= loadAndApplyTemplate "templates/base.html" postCtx 46 | >>= relativizeUrls 47 | 48 | 49 | -- build index page: 50 | match "content/index.html" $ do 51 | route (gsubRoute "content/" (const "")) 52 | compile $ do 53 | let indexCtx = field "posts" (\_ -> postList recentFirst) 54 | getResourceBody 55 | >>= applyAsTemplate indexCtx 56 | >>= loadAndApplyTemplate "templates/base.html" postCtx 57 | >>= relativizeUrls 58 | 59 | 60 | -- copy other site content: 61 | match "content/**" $ do 62 | route (gsubRoute "content/" (const "")) 63 | compile copyFileCompiler 64 | 65 | -- copy Zurb Foundation icon fonts into fonts directory 66 | match "bower_components/foundation-icon-fonts/foundation-icons*" $ do 67 | route (gsubRoute "bower_components/foundation-icon-fonts/" (const "fonts/")) 68 | compile copyFileCompiler 69 | 70 | -- compile SCSS: 71 | match "src/scss/main.scss" $do 72 | route $ constRoute "stylesheet.css" 73 | compile $ getResourceString 74 | >>= withItemBody (unixFilter "sass" ["-s", 75 | "--scss", 76 | "--compass", 77 | "--style", "compressed", 78 | "--load-path", "src/scss"]) 79 | >>= return . fmap compressCss 80 | 81 | 82 | -------------------------------------------------------------------------------- 83 | postCtx :: Context String 84 | postCtx = 85 | dateField "date" "%B %e, %Y" `mappend` 86 | defaultContext 87 | 88 | 89 | -------------------------------------------------------------------------------- 90 | postList :: ([Item String] -> Compiler [Item String]) -> Compiler String 91 | postList sortFilter = do 92 | posts <- sortFilter =<< loadAll postsDirectory 93 | itemTpl <- loadBody "templates/post-list-item.html" 94 | list <- applyTemplateList itemTpl postCtx posts 95 | return list 96 | -------------------------------------------------------------------------------- /posts/symbols.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: symbols 3 | description: A list of handy/pretty/interesting Unicode symbols. 4 | date: 2013-04-16 5 | ----- 6 | 7 | intellectual property symbols 8 | ----------------------------- 9 | 10 | symbol meaning 11 | ------ ------- 12 | © copyright (C) yyyy [Owner] 13 | ® registered trademark 14 | ℠ service mark 15 | ℗ sound recording copyright 16 | ™ trademark 17 | 18 | 19 | punctuation 20 | ----------- 21 | 22 | symbol meaning 23 | ------ ------- 24 | ⸮ percontation point/ironicon 25 | ‽ interrobang 26 | … ellipsis (pre-composed) 27 | ⋯ mid-line ellipsis 28 | • bullet 29 | ‣ triangular bullet 30 | ⬩ 31 | · interpunct (between words) 32 | 〃 ditto mark 33 | 34 | 35 | general typography 36 | ------------------ 37 | 38 | symbol meaning 39 | ------ ------- 40 | – en-dash (used – with – spaces) 41 | — em-dash (used—without—spaces) 42 | ¶ pilcrow (paragraph mark) 43 | § section sign 44 | № numero sign 45 | ‰ per mille sign 46 | ‱ per ten thousand sign (1 basis point (bp) = 1 permyriad = one one-hundredth percent) 47 | ฿ bitcoin 48 | £ pound sterling 49 | 50 | 51 | mathematics 52 | ----------- 53 | 54 | symbol meaning 55 | ------ ------- 56 | ′″‴ primes/dashes 57 | ± plus-minus sign 58 | ✕ multiplication x 59 | ∙ bullet operator (dot product) 60 | ° degree sign 61 | ∝ proportional to 62 | ∞ infinity sign/lemniscate 63 | ℵ the first trans-finite cardinal (Alef) 64 | ℓ a line ('ell' sign) 65 | ⟨⟩ angle brackets/chevrons (average over time/continuous parameter) 66 | ⟦⟧ double brackets (Strachey brackets/semantic evaluation function) 67 | 68 | 69 | logic symbols 70 | ------------- 71 | 72 | symbol meaning 73 | ------ ------- 74 | ∴ therefore 75 | ∵ because 76 | ⊤ tee (tautology) 77 | ⊥ up tack (contradiction/falsum) 78 | ⊢ right tack (provable from) 79 | 80 | The most comprehensive and useful list is probably 81 | the [Wikipedia List of Logic Symbols][], and it'll give you a decent 82 | overview of basic logic, which is a bonus! 83 | 84 | 85 | sets 86 | ---- 87 | 88 | symbol meaning 89 | ------ ------- 90 | ℕ natural numbers 91 | ℤ integers 92 | ℝ real numbers 93 | ℚ rational numbers 94 | ℂ complex numbers 95 | ⨝ join 96 | 97 | miscellaneous 98 | ------------- 99 | 100 | symbol meaning 101 | ------ ------- 102 | ❦ floral heart (aldus leaf) 103 | ❧ rotated floral heart bullet (hedera, ivy leaf) 104 | ☙ reversed rotated floral heart bullet (a binding signature mark) 105 | ❤ heavy black heart 106 | ✉ envelope 107 | ✌ victory hand 108 | ✓ check mark 109 | ✗ ballot x 110 | ⭐ white medium star 111 | ❖ diamond minus white x 112 | ➟ dashed triangle-headed rightwards arrow 113 | ➠ heavy dashed triangle-headed rightwards arrow 114 | ➼ wedge-tailed rightwards arrow 115 | ➤ 116 | ➺ 117 | ➻ 118 | ⁌⁍ 119 | ↺ 120 | ⊛ circled multiplier operator 121 | ⌬ benzene ring 122 | ⌖ true position 123 | ⌚ watch 124 | ☉ gold (alchemy) 125 | ⍿ vertical sign with middle dot 126 | ⚒ hammer and pick (mining/working day) 127 | ⚔ crossed swords (military term) 128 | ⚓ anchor 129 | ⚖ scales 130 | ⚗ alembic 131 | ⚘ flower 132 | ⚙ gear 133 | ⚛ atom symbol 134 | ⚜ fleur-de-lis 135 | ⚝ outlined white star 136 | ⚠ warning sign 137 | ⚡ high voltage sign 138 | ☭ hammer and sickle 139 | ☮ peace symbol 140 | ☯ yin yang 141 | ☸ wheel of dharma 142 | ✇ tape drive 143 | ☢ radioactive sign 144 | ☠ skull and crossbones 145 | ☣ biohazard sign 146 | ♲ universal recycling symbol 147 | ♻ black universal recycling symbol 148 | ☼ white sun with rays 149 | ☀ black sun with rays 150 | ☁ cloud 151 | ☂ umbrella 152 | ☔ umbrella with rain drops 153 | ☕ hot beverage (can be used to indicate a weight) 154 | 155 | 156 | 157 | 158 | [Wikipedia List of Logic Symbols]: https://en.wikipedia.org/wiki/List_of_logic_symbols 159 | -------------------------------------------------------------------------------- /posts/linux-processes.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: Linux Processes 3 | description: Manipulating processes from the shell. 4 | date: 2012-10-26 5 | ----- 6 | 7 | **Note**: Mostly stolen from a [Tardis][] [beginner 8 | tutorial](http://www.tardis.ed.ac.uk/wiki/Tardis_Beginner_Tutorials/8). 9 | 10 | 11 | Background & Foreground Processes 12 | --------------------------------- 13 | 14 | Appending `&` to a command $c$ will run it as a background process: 15 | 16 | ```bash 17 | {c} & 18 | ``` 19 | 20 | To move a running process to the background, hit ctrl-z. This 21 | will freeze it, and return you to the prompt - then you can either type 22 | `bg` to allow it to run in the background, without your input, or `fg` to 23 | bring it back to the foreground. You can bring your frozen command $c$ 24 | back to the foreground by typing: 25 | 26 | ```bash 27 | fg 28 | ``` 29 | 30 | or allow it to run in the background by typing: 31 | 32 | ```bash 33 | bg 34 | ``` 35 | 36 | 37 | Listing Processes 38 | ----------------- 39 | 40 | To list the processes you have running you can simply type `ps`. You will 41 | likely only see two: `bash`, and `ps` itself. A more informative `ps` 42 | command is: 43 | 44 | ```bash 45 | ps auxf | less 46 | ``` 47 | 48 | This lists all processes, both userland and system, with users shown 49 | alongside their processes, regardless of tty. A process hierarchy display 50 | shows graphically which processes are children of which. The output is 51 | rather long, showing both userland and system processes. 52 | 53 | The two most useful things to be found on the process list are: 54 | 55 | * the "PID" -- the 4- or 5-digit number used to reference 56 | individual processes 57 | * the "nice" -- telling the kernel how much CPU time the individual 58 | process should be given relative to other processes 59 | 60 | 61 | Process Manipulation 62 | -------------------- 63 | 64 | ### Killing a process 65 | 66 | To kill an uncooperative process, we can do one of two things: 67 | 68 | * bring the process to the foreground with `fg` and interrupt it 69 | by pressing ctrl-c 70 | * `kill` the process 71 | 72 | To kill a process, type: 73 | 74 | ```bash 75 | kill [PID of process] 76 | ``` 77 | 78 | It should dissapear from the processes list. 79 | 80 | Sometimes uncooperative processes don't die with just the standard TERM 81 | signal, in which case you want to send it a KILL signal by typing: 82 | 83 | ```bash 84 | kill -s 9 [PID of process] 85 | ``` 86 | 87 | It's worth reading `man kill` as it explains different signals - you will 88 | see that kill can be used to send other signals to processes, such as HUP 89 | which is used fairly often. 90 | 91 | 92 | ### Prioritizing processes with `nice` 93 | 94 | To start a command $c$ with a specific "nice" priority $n$, run 95 | 96 | ```bash 97 | nice -n {n} {c} 98 | ``` 99 | 100 | The "nice" priority assigned to a process is only taken as a guide, 101 | saying to the kernel that your process doesn't need to go over a priority 102 | of $n$. The kernel assigns real priorities based on system 103 | load and other factors. 104 | 105 | The default nice $n$ of a process $p$ is 10. 106 | 107 | For non-root users, the nice $n$ of a process must be $0 < n < 19$. The 108 | highest priority is 0, demanding the process's maximum fair share of CPU 109 | time available. 19 is the lowest priority, meaning it will use only idle 110 | CPU time that no other process wants. 111 | 112 | The root user can create processes with priorities < 0, which 113 | aggressively grab CPU time whether they need it or not. 114 | 115 | 116 | #### Prioritizing already-running processes 117 | 118 | Say we want to tame a resource-hogging process $p$. 119 | 120 | First, we need the process to be running in the background, so we can 121 | take control of it. If we have the the PID of the process $p$, we can 122 | decrease its nice $n$ with: 123 | 124 | ```bash 125 | renice ±{n} {PID p} 126 | ``` 127 | 128 | If you look at the listing in `top` again, $p$'s nice priority should 129 | have changed to $n$. If the system is still busy, it's because the actual 130 | priority hasn't changed -- it's often a higher number to start with than 131 | your requested/nice priority. 132 | 133 | 134 | To force the process $p$ to absolute minimum priority, type: 135 | 136 | ```bash 137 | renice +19 {PID p} 138 | ``` 139 | 140 | This drops $p$'s nice priority to 19, so that if another process 141 | wants more CPU time, then $p$ will step out of the way. 142 | 143 | Only the root user can increase the nice $n$ of a process $p$, although 144 | any user can create a process where $0 < n < 19$, or reduce the priority 145 | (by increasing $n$) while it's running. 146 | 147 | 148 | 149 | 150 | [Tardis]: http://www.tardis.ed.ac.uk 151 | -------------------------------------------------------------------------------- /posts/pandoc-syntax-highlighting-css.md: -------------------------------------------------------------------------------- 1 | ----- 2 | title: Pandoc Syntax Highlighting with CSS 3 | description: Improving Pandoc's syntax-highlighting with Solarized and some CSS. 4 | date: 2013-04-24 5 | ----- 6 | 7 | [John Macfarlane's Pandoc][pandoc] is an awesome tool for writing 8 | documents. One of my favourite features is its extended Markdown syntax; 9 | especially the [GitHub][gh-syntax]-style 10 | [fenced code-blocks][code-blocks], 11 | which let you write code inside a Markdown file like this: 12 | 13 | ```bash 14 | cd some_dir 15 | grep "some text" 16 | # etc... 17 | ``` 18 | 19 | and get out this: 20 | 21 | ```bash 22 | cd some_dir 23 | grep "some text" 24 | # etc... 25 | ``` 26 | 27 | However, the [stylesheet provided with Pandoc][pandoc css] isn't winning 28 | any design awards, so I decided to write one which would decorate 29 | Pandoc's output with something [more well-known][solarized]! 30 | 31 | 32 | The `highlighting-kate` Package 33 | ------------------------------- 34 | 35 | Unless you dig into Pandoc's [Haddock documentation][pandoc-docs], you 36 | won't find much information on the internet telling you what the 37 | generated markup classes (`.kw`, `.co`, `.ot`, etc.) mean, or how you can 38 | customize them. 39 | 40 | It turns out that Pandoc relies on another one of John Macfarlane's 41 | creations in order to mark up code syntax, the [`highlighting-kate` 42 | package][hk], 43 | 44 | > a syntax highlighting library with support for nearly one hundred 45 | > languages. The syntax parsers are automatically generated from Kate 46 | > syntax descriptions (http://kate-editor.org/), so any syntax supported 47 | > by Kate can be added. [`highlighting-kate` package description][hk] 48 | 49 | So it turns out that the syntax tokens are based on definitions provided 50 | by the KDE text editor, [Kate][]. 51 | 52 | According to the documentation for `highlighting-kate`'s 53 | [HTML Formatters][hk-html], the classes used to mark-up 54 | syntax tokens are as follows: 55 | 56 | span class code token 57 | --------------- ----------------------- 58 | `.kw` Keyword 59 | `.dt` DataType 60 | `.dv` DecVal (decimal values) 61 | `.bn` BaseN 62 | `.fl` Float 63 | `.ch` Char 64 | `.st` String 65 | `.co` Comment 66 | `.ot` OtherToken 67 | `.at` AlertToken 68 | `.fu` Function 69 | `.re` RegionMarker 70 | `.er` ErrorTok 71 | 72 | These classifications are (sort of) explained in an old HOWTO on the 73 | Kate site for [writing syntax-highlighting files][kate-syntax]. 74 | 75 | It also turns out that a few extra styles are [included][hk-styles] with 76 | the `kate-highlighting` package, if you want to extract and use them! 77 | 78 | 79 | a Solarized Light colour-scheme for Pandoc 80 | ------------------------------------------ 81 | 82 | Since I wanted something a little more distinctive, I decided to 83 | reimplement one of [Ethan Schoover's Solarized colour-schemes][solarized] 84 | for the Pandoc/`highlighting-kate`'s markup, as I could only find 85 | versions for [Google Code and Codemirror][css-solarized]. It's not 86 | perfect, as Kate's syntax-highlighting, er, syntax isn't very expansive, 87 | but it's more than adequate for web viewing! 88 | 89 | This is the CSS for putting Pandoc's code-blocks into Solarized Light: 90 | 91 | ```css 92 | pre { 93 | background-color: #FDF6E3 94 | } 95 | 96 | // KeyWordTok 97 | .sourceCode .kw { color: #268BD2; } 98 | // DataTypeTok 99 | .sourceCode .dt { color: #268BD2; } 100 | 101 | // DecValTok (decimal value), BaseNTok, FloatTok 102 | .sourceCode .dv, .sourceCode .bn, .sourceCode .fl { color: #D33682; } 103 | // CharTok 104 | .sourceCode .ch { color: #DC322F; } 105 | // StringTok 106 | .sourceCode .st { color: #2AA198; } 107 | // CommentTok 108 | .sourceCode .co { color: #93A1A1; } 109 | // OtherTok 110 | .sourceCode .ot { color: #A57800; } 111 | // AlertTok 112 | .sourceCode .al { color: #CB4B16; font-weight: bold; } 113 | // FunctionTok 114 | .sourceCode .fu { color: #268BD2; } 115 | // RegionMarkerTok 116 | .sourceCode .re { } 117 | // ErrorTok 118 | .sourceCode .er { color: #D30102; font-weight: bold; } 119 | ``` 120 | 121 | The actual code in use on [benjeffrey.com](/) is written [as a Sass mixin 122 | ][sass-mixin]. 123 | 124 | 125 | 126 | 127 | 128 | [pandoc]: http://www.johnmacfarlane.net/pandoc/index.html 129 | [code-blocks]: http://www.johnmacfarlane.net/pandoc/README.html#fenced-code-blocks 130 | [gh-syntax]: https://help.github.com/articles/github-flavored-markdown#syntax-highlighting 131 | [hk]: http://hackage.haskell.org/package/highlighting-kate 132 | [pandoc-docs]: http://hackage.haskell.org/package/pandoc 133 | [Kate]: http://kate-editor.org/ 134 | [hk-html]: http://hackage.haskell.org/packages/archive/highlighting-kate/0.5.3.8/doc/html/Text-Highlighting-Kate-Format-HTML.html 135 | [hk-styles]: http://hackage.haskell.org/packages/archive/highlighting-kate/0.5.3.8/doc/html/Text-Highlighting-Kate-Styles.html 136 | [kate-syntax]: http://kate-editor.org/2005/03/24/writing-a-syntax-highlighting-file/ 137 | [solarized]: http://ethanschoonover.com/solarized 138 | [css-solarized]: http://css-tricks.com/snippets/css/solarized-theme-for-codemirror-and-prettify/ 139 | [sass-mixin]: https://github.com/jeffbr13/benjeffrey.com/blob/master/scss/_syntax-highlighting-solarized-light.scss 140 | [pandoc css]: http://jaspervdj.be/hakyll/tutorials/faq.html#does-hakyll-support-syntax-highlighting 141 | -------------------------------------------------------------------------------- /posts/why-eusa-was-right-to-ban-blurred-lines.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Why EUSA Was Right To Ban "Blurred Lines" 3 | date: 2013-09-20 4 | description: As EUSA's campus ban of "Blurred Lines" is snowballing across the world, here's my opinion. 5 | --- 6 | 7 | I've been surprised by the amount of backlash against [Robin Thicke's track with the rapey lyrics](http://www.lyrics.com/blurred-lines-lyrics-robin-thicke.html) being banned across more and more UK campuses. Our [student union](http://www.eusa.ed.ac.uk/) here at the University of Edinburgh was, I believe, the first to ban "Blurred Lines" due to a combination of: 8 | 9 | 1. EUSA's zero-tolerance [sexual harassment campaign/policy](http://www.eusa.ed.ac.uk/societies/run/training/zerotolerancecampaign/), and 10 | 2. Our Freshers Week being earlier than most (16th September onwards). 11 | 12 | Upon returning for Freshers, a fair few of my student chums expressed outrage at EUSA seeming to act out yet again, and this time against one of summer's [most popular singles](http://www.billboard.com/articles/news/5687036/robin-thickes-blurred-lines-is-billboards-song-of-the-summer). 13 | 14 | But first, a bit of background: although I'm not familiar with any other student unions, EUSA is often regarded by UoE students as having a rather heavy hand. Last year, for example, we had [a large brouhaha](http://www.theguardian.com/media/2013/feb/11/student-newspaper-gagged-edinburgh-university) when [they gagged The Student with an injunction](http://www.studentnewspaper.org/tag/injunction/), supposedly over protecting an employee's privacy, but at first glance because of internal politics. Personally, I'm *still* unsure what occurred, and I don't really care enough to find out what it was all about. 15 | 16 | I'm not surprised that many see EUSA's "Blurred Lines" ban as further proof of a willingness to use censorship as a first resort against, well... everything. But, as much distaste as I have for student politics, I don't support this hypothesis. 17 | 18 | ## What Did EUSA Actually Do? 19 | 20 | Did EUSA overexert their powers in this situation? I would say not. 21 | 22 | - They banned a single song from playing in venues which they operate, 23 | - In doing so, they increased awareness of misogyny in popular music, 24 | - The track was on it's way out anyway, 25 | - If you still want to hear it you can go *anywhere* else in Edinburgh. 26 | 27 | Talk about a proportional and effective response! At the very least they deserve an internet meme for all that: 28 | 29 | ![BANS OVERPLAYED POP SONG. SPARKS INTERNATIONAL DEBATE ON MISOGYNY.](../images/success-kid-blurred-lines-ban.png) 30 | 31 | At the end of the day, what did EUSA actually do? 32 | 33 | They did not 'ban' or 'censor' the track on campus, in any literal or meaningful sense; EUSA operates (owns?) the venues where the track is no longer allowed to be played. Without stepping on anybody's rights, it is perfectly entitled to choose it's songs or [refuse to sell products][page 3 ban] as it sees fit[^1]. 34 | 35 | And yes, if EUSA did follow it's zero-tolerance policy to it's logical conclusion then they'd have to stop playing a whole bunch of other songs, too. But banning songs isn't the point! I don't believe that (all) the folks at EUSA want to play moral arbiter and make people suffer by dictating what they can/can't listen to. They could have done that much more effectively by following their principle to the letter, actually banning a significant portion of modern recordings, and making their venues irrelevant in the process. But they're no Chairman Mao. This wasn't meant to be cultural revolution, it was *targeted assassination*. 36 | 37 | **EUSA have banned a popular (but fading) track so that we have this debate in the first place.** After all, if you still want to hear Blurred Lines in a club, there are plenty of venues in Edinburgh which will happily play radio-music for you every night of the week[^2]. 38 | 39 | The University of Edinburgh has apparently been subject to ["public humiliation"](http://tychy.wordpress.com/2013/09/15/another-eusa-censorship-disaster/) in the [national](http://www.bbc.co.uk/newsbeat/24071219) (and now [international](https://news.google.com/news?ned=us&q=blurred%20lines%20eusa%20ban&btnG=Search+News)) press because of EUSA taking this stand, 'over a song', but hey, you're the ones wailing about it. And all this debate still sounds better than hearing *that damn song again*... 40 | 41 | [page 3 ban]: http://www.journal-online.co.uk/article/9288-eusa-referendum-debate-sparks-indepth-discussion "There was an attempt to ban The Sun newspaper in EUSA shops last October, but I'm not sure whether it was successful or not." 42 | 43 | 44 | [^1]: UPDATE: To clarify further, there are two reasons why this is not censorship: 45 | 1. As an entity, EUSA is entitled to play whatever it likes on it's own damn property, much in the same way I am. If I were in charge of club playlists, I'd have a *much* longer list of "no-play" songs. However, my refusal to blare [Rebecca Black's 'Friday'](https://www.youtube.com/watch?v=kfVsfOSbJY0) on my laptop or theoretical club soundsystem does not constitute censorship of this track either. The difference is that in most venues you can only vote with your feet/wallets, but since EUSA is a democratic organization, [you have representatives](http://www.eusa.ed.ac.uk/getinvolved/elections/yourrepresentatives/find/) to complain at, if you want a policy changed! 46 | 2. Again, this isn't really a "campus-wide ban". EUSA does not want EUSA employees to play the track in question on EUSA property. You can still blare "Blurred Lines" on your phone in Bristo Square, or listen to it on your headphones in the library if you like. EUSA have no power to impose any sort of restriction on your poor taste. :-) 47 | 48 | [^2]: I personally found the DJ at [Castle Clvb](http://www.theskinny.co.uk/venue/9432-castle_club) last Saturday night to be extremely entertaining. Not only did he have a library consisting entirely of circa 2007 rap music (i.e. 50 Cent and Eminem) but he also had this ability, nay *need*, to change tracks every 90 seconds on the dot! 2.5/5, funniest DJ set ever. 49 | -------------------------------------------------------------------------------- /content/cv.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: curriculum vitae 3 | description: Where Ben Jeffrey has been, and what he's done. 4 | --- 5 | 6 | 17 | 18 | 19 | Education 20 | --------- 21 | 22 | ### [University of Edinburgh](http://www.ed.ac.uk) 23 | 24 | Currently on a year out from studying for a [Masters of Informatics (MInf.)][minf] and due to graduate in 2017. 25 | 26 | #### Informatics Courses 27 | 28 | - [Functional Programming](http://www.inf.ed.ac.uk/teaching/courses/inf1-fp), Haskell 29 | - [Object-Oriented Programming](http://www.inf.ed.ac.uk/teaching/courses/inf1-op), Java (wrote a game, team won class "teamwork" prize) 30 | - [Cognitive Science](http://www.inf.ed.ac.uk/teaching/courses/inf1-cg), an introductory course 31 | - [Processing Formal and Natural Languages](http://www.inf.ed.ac.uk/teaching/courses/inf2a/) 32 | - [Computer Systems](http://www.inf.ed.ac.uk/teaching/courses/inf2c-cs/), MIPS and C 33 | - [Software Engineering](http://www.inf.ed.ac.uk/teaching/courses/inf2c-se/) 34 | - [Discrete Mathematics and Mathematical Reasoning](http://www.inf.ed.ac.uk/teaching/courses/dmmr/) 35 | 36 | 37 | Employment 38 | ---------- 39 | 40 | ### API Software Engineer Intern, [School of Engineering, University of Edinburgh](http://eng.ed.ac.uk) (Summer 2014) 41 | 42 | Internship at Edinburgh's school of engineering, tasked with building a ReST API for the university's Blackboard Learn VLE. Although the project wasn't completed during my stay, I did learn a fair bit about the state of most enterprise software! 43 | 44 | 45 | ### Technical Co-founder, [Pitchpatch/ptchd](http://www.ptchd.com) (Summer 2013) 46 | 47 | Successfully built and demonstrated a prototype 'skills-marketplace' for university campuses, having been granted a £5,000 [Summer of Student Innovation](http://jisc.ac.uk/student-innovation) grant from [Jisc](http://jisc.ac.uk/). 48 | 49 | 50 | ### Data Acquisition Software Engineer, [Skyscanner](http://skyscanner.net) (October 2013 → May 2014) 51 | 52 | Previous work continued on a part-time basis. 53 | 54 | 55 | ### Data Acquisition Intern, [Skyscanner](http://skyscanner.net) (Summer 2013) 56 | 57 | I worked with a team of other interns, maintaining and growing Skyscanner's 58 | large collection of international airline scrapers, written in Python. 59 | Duties included maintaining and updating database records, as well as 60 | interfacing with airline counterparts in resolving issues with APIs or 61 | webscrapers. 62 | 63 | 64 | ### Telephone Interviewer, [Ipsos Mori Scotland](http://www.ipsos-mori.com/offices/scotland.aspx) (December 2012 → January 2013) 65 | 66 | Collecting survey data over the telephone, from participant feedback on 67 | government programs to the monthly political thermometer. Brought my own 68 | cuppas in a thermos. 69 | 70 | 71 | ### Waiter, [Fratello's Restaurant Scotch Corner](http://www.fratellosscotchcorner.co.uk/) (Summer 2012) 72 | 73 | Bussing tables, manning the bar, serving banquets. Not much time for tea. 74 | 75 | 76 | ### Junior Javascript Developer, [Accendo Design](http://www.accendodesign.com/) (July → August 2011) 77 | 78 | Three weeks of work experience, given the Rhino book to learn Javascript 79 | on the job, and wrote some webform validation code for a real-estate management 80 | startup. First tastes of many strange and exotic teas. 81 | 82 | ### Office Assistant, [Anarkik3D](http://www.anarkik3d.co.uk/) (June 2011) 83 | 84 | One week of work experience, which included 85 | playing with the company's 3D drafting software, writing 86 | a small Python application to interface with social networks, 87 | neatening up webpages, brewing the tea, and other essential 88 | office-work. 89 | 90 | 91 | Projects and Volunteering 92 | ------------------------- 93 | 94 | To see what I'm working on right now, check out [my GitHub page](https://github.com/jeffbr13?tab=repositories). 95 | 96 | I'm a member of the [Open Knowledge Foundation](http://scot.okfn.org/), 97 | and I've been involved with Open Data efforts in and around the University of Edinburgh. 98 | 99 | 100 | ### Hackathons 101 | 102 | Fairly-regular attendee of hackathons, including (but not limited to): 103 | 104 | * Startup Weekend 105 | * Day-of-Code Retreat 106 | * University of Edinburgh ILWHack (team won "Best Data Mashup" category, 2013) 107 | * [NHS Hack Scotland](http://www.nhshackscotland.org.uk) 108 | * [Product Forge](http://productforge.io) 1, 2, and 3 109 | * various [MLH](https://mlh.io) events 110 | 111 | 112 | ### Miscellaneous Projects 113 | 114 | - [Social Sounds Project](http://www.socialsoundsproject), a map of sounds around Edinburgh and Scotland, 115 | built for the Anthropology department at the University of Edinburgh 116 | 117 | 118 | Skills 119 | ------ 120 | 121 | ### Languages 122 | 123 | - Python 124 | - Java 125 | - JavaScript 126 | - CSS/Sass/Less 127 | - Haskell 128 | - Golang 129 | - SQL 130 | 131 | ### Software Stacks 132 | 133 | Previous experience with 134 | 135 | - [Django][] for web applications 136 | - [Flask][] for back-ends and small applications 137 | - Nginx, Apache 138 | - [Docker](https://www.docker.com) containerisation, specifically with [Docker Compose (previously Fig)](http://docs.docker.com/compose/). 139 | 140 | 141 | ### Miscellaneous Skills 142 | 143 | - familiarity with Agile methodology 144 | - experienced Linux user 145 | 146 | 147 | 148 | 149 | [minf]: http://www.inf.ed.ac.uk/student-services/teaching-organisation/taught-course-information/degree-programmes/master-of-informatics 150 | [Flask]: http://flask.pocoo.org/ 151 | [Hakyll]: http://jaspervdj.be/hakyll/ 152 | [flickr]: http://www.flickr.com/photos/jeffbr13/sets 153 | [Django]: https://www.djangoproject.com/ 154 | -------------------------------------------------------------------------------- /posts/agreement-wall.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: The Agreement Wall 3 | description: Latin nouns and adjectives. 4 | date: 2012-06-07 5 | --- 6 | 7 | nouns 8 | ----- 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | 57 | 58 | 59 | 60 | 61 | 62 | 63 | 64 | 65 | 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | 79 | 80 | 81 | 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 |
1st Declension (Fem.)2nd Declension (Masc.)2nd Declension (Neut.)3rd Declension (Masc/Fem/Neut.)4th Declension (Masc.)
SingularNominativepuellaservusbellumleoportus
Accusativepuellamservumbellumleonemportum
Genitivepuellaeservibellileonisportūs
Dativepuellaeservobelloleoniportui
Ablativepuellāservobelloleoneportu
PluralNominativepuellaeservibellaleonesportūs
Accusativepuellasservosbellaleonesportūs
Genitivepuellarumservorumbellorumleonumportuum
Dativepuellisservisbellisleonibusportibus
Ablativepuellisservisbellisleonibusportibus
125 | 126 | 127 | adjectives 128 | ---------- 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | 137 | 138 | 139 | 140 | 141 | 142 | 143 | 144 | 145 | 146 | 147 | 148 | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | 159 | 160 | 161 | 162 | 163 | 164 | 165 | 166 | 167 | 168 | 169 | 170 | 171 | 172 | 173 | 174 | 175 | 176 | 177 | 178 | 179 | 180 | 181 | 182 | 183 | 184 | 185 | 186 | 187 | 188 | 189 | 190 | 191 | 192 | 193 | 194 | 195 | 196 | 197 | 198 | 199 | 200 | 201 | 202 | 203 | 204 | 205 | 206 | 207 | 208 | 209 | 210 | 211 | 212 | 213 | 214 | 215 | 216 | 217 | 218 | 219 | 220 | 221 | 222 | 223 | 224 | 225 | 226 | 227 | 228 | 229 | 230 | 231 | 232 | 233 | 234 | 235 | 236 | 237 | 238 | 239 | 240 | 241 | 242 | 243 | 244 | 245 | 246 | 247 | 248 | 249 | 250 | 251 | 252 | 253 | 254 | 255 | 256 | 257 | 258 | 259 |
1st/2nd Declension3rd Declension
Masc.Fem.Neut.Masc./Fem.Neut.
SingularNominativemaestusmaestamaestumtrististriste
Accusativemaestummaestammaestumtristemtriste
Genitivemaestismaestaemaestistrististristis
Dativemaestomaestaemaestotristitristi
Ablativemaestomaestāmaestotristitristi
PluralNominativemaestimaestaemaestatristestristia
Accusativemaestosmaestasmaestatristestristia
Genitivemaestorummaestarummaestorumtristiumtristium
Dativemaestismaestismaestistristibustristibus
Ablativemaestismaestismaestistristibustristibus
260 | -------------------------------------------------------------------------------- /posts/ckan-ansible-playbook.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: CKAN ansible playbook 3 | date: 2014-05-05 4 | --- 5 | 6 | This Ansible playbook provisions a complete CKAN installation, 7 | following [the official CKAN package installation guide][1] 8 | on Ubuntu 12.04 LTS (Precise). 9 | 10 | It also configures some unattended upgrades, enables passwordless sudo, and may need to be executed twice. 11 | 12 | I've just thrown it together, and the new Ubuntu LTS release (14.04) has just come out, so please check the playbook 13 | before you run it. 14 | 15 | Comments welcome on [the Github gist](https://gist.github.com/jeffbr13/08751e42c9355cc44f5d). 16 | 17 | ```yaml 18 | --- 19 | - hosts: all 20 | 21 | sudo: yes 22 | 23 | vars: 24 | - db_name: ckan_default 25 | - db_user: ckan_default 26 | - db_password: ckan_default 27 | - ckan_package_filename: 'python-ckan_2.2_amd64.deb' 28 | 29 | tasks: 30 | 31 | - name: Update apt cache 32 | apt: update_cache=yes 33 | 34 | - name: Upgrade all safe packages 35 | apt: upgrade=safe 36 | 37 | - name: Install unattended upgrades (Debian/Ubuntu only) 38 | apt: pkg=unattended-upgrades state=installed 39 | when: ansible_distribution == 'Debian' or ansible_distribution == 'Ubuntu' 40 | 41 | - name: 'Make sure unattended-upgrades only installs from $ubuntu_release-security' 42 | lineinfile: 'dest=/etc/apt/apt.conf.d/50unattended-upgrades regexp="$ubuntu_release-updates" state=absent' 43 | when: ansible_distribution == 'Ubuntu' 44 | 45 | - name: Install necessities and nice-to-haves 46 | apt: pkg={{ item }} state=installed 47 | with_items: 48 | - acl 49 | - apache2 50 | - apt-transport-https 51 | - apticron 52 | - aptitude 53 | - build-essential 54 | - debian-goodies 55 | - fail2ban 56 | - git 57 | - htop 58 | - iftop 59 | - iotop 60 | - libapache2-mod-wsgi 61 | - libpq5 62 | - nginx 63 | - postgresql 64 | - python 65 | - python-psycopg2 66 | - python-pycurl 67 | - python-software-properties 68 | - screen 69 | - solr-jetty 70 | - sudo 71 | - update-notifier-common 72 | - wget 73 | when: ansible_pkg_mgr == 'apt' 74 | 75 | - name: Enable passwordless sudo 76 | lineinfile: 'dest=/etc/sudoers regexp="sudo ALL=NOPASSWD: ALL" line="%sudo ALL=NOPASSWD: ALL" state=present' 77 | 78 | - name: Download CKAN package 79 | get_url: 'url="http://packaging.ckan.org/{{ ckan_package_filename }}" dest=/tmp/{{ ckan_package_filename }}' 80 | 81 | - name: Install CKAN package 82 | command: 'dpkg --skip-same-version -i /tmp/{{ ckan_package_filename }}' 83 | # http://stackoverflow.com/questions/19127493/in-ansible-how-do-you-prevent-a-dpkg-installation-task-to-notify-a-changed-stat 84 | register: ckan_installed 85 | changed_when: "'already installed' not in ckan_installed.stderr" 86 | notify: 87 | - Restart Apache 88 | - Restart Nginx 89 | 90 | # Jetty & Solr 91 | - name: Set Jetty to start on boot 92 | lineinfile: 'dest=/etc/default/jetty regexp=^NO_START line="NO_START=0"' 93 | 94 | - name: Set Jetty host to localhost 95 | lineinfile: 'dest=/etc/default/jetty regexp=^JETTY_HOST line="JETTY_HOST=127.0.0.1"' 96 | 97 | - name: Set Jetty to port 8983 98 | lineinfile: 'dest=/etc/default/jetty regexp=^JETTY_PORT line="JETTY_PORT=8983"' 99 | 100 | - name: Set Jetty to use system java 101 | lineinfile: 'dest=/etc/default/jetty regexp=JAVA_HOME line="JAVA_HOME=/usr/lib/jvm/java-6-openjdk-amd64/"' 102 | notify: Start Jetty 103 | 104 | - name: Remove CKAN schema file 105 | file: path=/etc/solr/conf/schema.xml state=absent 106 | when: ckan_installed.changed 107 | 108 | - name: Ensure CKAN uses provided schema file 109 | file: path=/etc/solr/conf/schema.xml src=/usr/lib/ckan/default/src/ckan/ckan/config/solr/schema.xml state=link 110 | notify: Restart Jetty 111 | 112 | - name: Set CKAN Solr server address 113 | lineinfile: 'dest=/etc/ckan/default/production.ini regexp=solr_url line=solr_url=http://127.0.0.1:8983/solr' 114 | 115 | # Postgres 116 | - name: Ensure CKAN database is created 117 | postgresql_db: 'name={{ db_name }}' 118 | sudo_user: postgres 119 | 120 | - name: Ensure CKAN database user can access CKAN database 121 | postgresql_user: 'db={{ db_name }} name={{ db_user }} password={{ db_password }} priv=ALL' 122 | sudo_user: postgres 123 | 124 | - name: Minimise CKAN database user priveliges 125 | postgresql_user: 'name={{ db_user }} role_attr_flags=NOSUPERUSER,NOCREATEROLE,NOCREATEDB' 126 | sudo_user: postgres 127 | 128 | - name: Set CKAN database server address 129 | lineinfile: 'dest=/etc/ckan/default/production.ini regexp=sqlalchemy.url line="sqlalchemy.url = postgresql://{{ db_user }}:{{ db_password }}@localhost/{{ db_name }}?sslmode=disable"' 130 | 131 | - name: Ensure database is initialised 132 | command: ckan db init 133 | notify: 134 | - Restart Apache 135 | - Restart Nginx 136 | 137 | - name: Remove Repoze.who configuration file for CKAN 138 | file: path=/usr/lib/ckan/default/src/ckan/who.ini state=absent 139 | when: ckan_installed.changed 140 | 141 | - name: Link Repoze.who configuration file for CKAN 142 | file: 'path=/usr/lib/ckan/default/src/ckan/who.ini src=/etc/ckan/default/who.ini state=link' 143 | 144 | # DataStore 145 | - name: Ensure DataStore database exists 146 | postgresql_db: name=datastore_default owner=ckan_default 147 | sudo_user: postgres 148 | 149 | - name: Ensure CKAN database user owns DataStore database 150 | postgresql_user: 'db=datastore_default name=ckan_default password={{ db_password }} priv=ALL' 151 | sudo_user: postgres 152 | 153 | - name: Ensure DataStore database user exists 154 | postgresql_user: 'name=datastore_default password={{ db_password }}' 155 | sudo_user: postgres 156 | 157 | - name: Set DataStore database server write address 158 | lineinfile: 'dest=/etc/ckan/default/production.ini regexp="ckan.datastore.write_url" line="ckan.datastore.write_url = postgresql://ckan_default:{{ db_password }}@localhost/datastore_default"' 159 | 160 | - name: Set DataStore database server read address 161 | lineinfile: 'dest=/etc/ckan/default/production.ini regexp="ckan.datastore.read_url" line="ckan.datastore.read_url = postgresql://datastore_default:{{ db_password }}@localhost/datastore_default"' 162 | 163 | - name: Set DataStore database permissions 164 | command: ckan datastore set-permissions postgres 165 | 166 | # FileStore 167 | - name: Ensure FileStore directory exists 168 | file: path=/var/lib/ckan/default owner=www-data state=directory 169 | 170 | - name: Set FileStore directory path 171 | lineinfile: 'dest=/etc/ckan/default/production.ini regexp="ckan.storage_path" line="ckan.storage_path = /var/lib/ckan/default"' 172 | 173 | - name: Ensure Apache can write to FileStore directory 174 | acl: name=/var/lib/ckan/default entity=www-data etype=user permissions=u+rwx 175 | notify: Restart Apache 176 | 177 | 178 | handlers: 179 | - name: Restart Apache 180 | service: name=apache2 state=restarted 181 | 182 | - name: Restart Nginx 183 | service: name=nginx state=restarted 184 | 185 | - name: Start Jetty 186 | service: name=jetty state=started 187 | 188 | - name: Restart Jetty 189 | service: name=jetty state=restarted 190 | ``` 191 | 192 | [1]: http://docs.ckan.org/en/latest/maintaining/installing/install-from-package.html 193 | -------------------------------------------------------------------------------- /posts/setting-up-gandi-ssl-on-nginx.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Setting up Gandi SSL on Nginx 3 | description: How to get an HTTPS padlock and use it, with Nginx 4 | date: 2013-04-30 5 | --- 6 | 7 | So I decided to add a nice little [HTTPS][] padlock to 8 | [benjeffrey.com][], having read Lukasa's article "[HTTPS All The 9 | Things][lukasa]". After all, some amount of encryption is always better 10 | than none, as a rule[^CAs]. Even for websites without authentication, 11 | such as this one. Esteemed software blogger Jeff Atwood weighs in on the 12 | issue too, asking "[Should All Web Traffic Be Encrypted?][]"[^ch]. 13 | 14 | ![Requisite meme.](../images/encrypt-all-the-things.png) 15 | 16 | I reckon (in a totally subjective manner) that there's also a certain 17 | element of credibility conferred by that padlock next to your URL - 18 | similar to the comfort of the familiar dotcom, when compared to the 19 | perceived sketchiness of a [.ru](https://en.wikipedia.org/wiki/.ru) or 20 | the hipster-startup vibe of a [.ly](https://en.wikipedia.org/wiki/.ly) 21 | address. 22 | 23 | I recently registered my domain at Gandi.net, and since they provide [a 24 | free SSL certificate for the first year][Gandi SSL], there wasn't any 25 | harm in trying one out. 26 | 27 | This page documents the process I went through to get and install an SSL 28 | certificate in order to encrypt web traffic passing between my personal 29 | website and you, my esteemed readers! 30 | 31 | My setup is just [a static website][building] hosted on an Nginx 32 | webserver, so it wasn't hard to find documentation to set up SSL (see 33 | the [Resources] section for deets). To reproduce my steps, simply follow 34 | the instructions outlined below, replacing `benjeffrey.com` etc. with 35 | your own domain name... You'll figure it out. 36 | 37 | 38 | Getting your SSL Certificate 39 | ---------------------------- 40 | 41 | **Requirements**: [OpenSSL](https://www.openssl.org/), and a [Certificate 42 | Authority][CA] to verify your certificate. 43 | 44 | ### Generate an RSA Keypair 45 | 46 | Connections with SSL are negotiated using asymmetric public-key 47 | encryption ([approximately][ssl]). The client uses your site's public key 48 | to encrypt packets to the webserver, which then decrypts them with its 49 | private key, before the connection drops to computationally-cheaper 50 | symmetric encryption. 51 | 52 | So our first step is generating this aforementioned public/private 53 | keypair with OpenSSl: 54 | 55 | ```bash 56 | openssl genrsa -des3 -out benjeffrey.com_encrypted.key 4096 57 | ``` 58 | 59 | This will prompt you to set a passphrase to secure the private part of your keypair. Do that. 60 | 61 | 62 | ### Generate a Certificate Signing Request 63 | 64 | A [CSR] is a file sent to Certificate Authorities containing the 65 | information to be included in your SSL certificate, including the public 66 | key that clients will use to communicate with your webserver. 67 | 68 | To generate your CSR, 69 | execute: 70 | 71 | ```bash 72 | openssl req -new -key benjeffrey.com_encrypted.key -out benjeffrey.com.csr 73 | ``` 74 | 75 | And answer the questions you're given. 76 | 77 | 78 | ### Get Your Certificate Signed by Gandi 79 | 80 | In the SSL certificate-signing process (which requires you to prove 81 | owneship of your domain) you'll upload your CSR, `benjeffrey.com.csr`, to 82 | Gandi. If you choose the DNS record method, then don't be surprised if 83 | verification takes a few hours - I left the process for a day, then came 84 | back to it once everything had propagated. 85 | 86 | ![You've unlocked Gandi.net's certification badge. Wow, this site must be secure!](https://www.gandi.net/static/static/img/ssl/GANDI_SSL_logo_B_std_en.png) 87 | 88 | Once this is done, you can download your newly CA-signed certificate (and 89 | rename it to `benjeffrey.com.crt` in the process). 90 | 91 | You'll also need [Gandi's intermediate certificate][Gandi cert], 92 | `GandiStandardSSLCA.pem`. 93 | 94 | 95 | Setting up Nginx for SSL 96 | ------------------------ 97 | 98 | ### Configure Certificates and Keys 99 | 100 | Since Nginx doesn't combine chain certificates itself, you need to append 101 | any and all intermediate certificates to your server certificate, 102 | according to the [HttpSsl Module docs][HttpSsl]. I found that 103 | the Gandi-issued certificate is missing a newline at the end, 104 | causing Nginx to throw an error unless you add one yourself, 105 | before concatenating it with the intermediate certificate: 106 | 107 | ```bash 108 | echo "\n" >> benjeffrey.com.crt 109 | cat benjeffrey.com.crt GandiStandardSSLCA.pem > benjeffrey.com.crt 110 | ``` 111 | 112 | Nginx also needs to be able to access the private key we created before, 113 | to decode packets encypted with the public key in your certificate. 114 | Aditionally, the private key should only be accessible to the user 115 | running the nginx process. So we remove the passphrase from the private 116 | key, and change it's owner and permissions to be more restrictive: 117 | 118 | ```bash 119 | openssl rsa -in benjeffrey.com_encrypted.key -out benjeffrey.com.key 120 | # root usually runs the nginx process: 121 | chown root:root benjeffrey.com.key 122 | chmod 400 benjeffrey.com.key 123 | ``` 124 | 125 | 126 | ### Configure your Site 127 | 128 | The following server directives tell Nginx to 129 | 130 | 1. serve `benjeffrey.com` over HTTPS only, and 131 | 2. to redirect any clients which try to access `http://benjeffrey.com` 132 | to the equivalent HTTPS address, 133 | with a [301 Moved Permanently][301] status code: 134 | 135 | ``` 136 | server { 137 | server_name benjeffrey.com; 138 | root /var/www/benjeffrey.com; 139 | listen 443 ssl; 140 | ssl_certificate /etc/nginx/ssl/benjeffrey.com.crt; 141 | ssl_certificate_key /etc/nginx/ssl/benjeffrey.com.key; 142 | 143 | location / { 144 | index index.html index.htm index; 145 | try_files $uri $uri/ $uri.html =404; 146 | } 147 | } 148 | 149 | # redirect HTTP traffic to HTTPS 150 | server { 151 | server_name benjeffrey.com 152 | listen 80; 153 | return 301 https://benjeffrey.com$request_uri; 154 | } 155 | ``` 156 | 157 | The actual configuration file used for benjeffrey.com is [available on 158 | GitHub][nginx-conf]. 159 | 160 | 161 | Resources 162 | --------- 163 | 164 | * 165 | * 166 | * 167 | * 168 | * 169 | 170 | 171 | 172 | 173 | [^CAs]: Although all forms of encryption are not created equal. 174 | As Lukasa [points out][lukasa]: 175 | 176 | > the whole notion of [certificate authorities][CA] is a pretty sketchy one 177 | 178 | The commonly-accepted wisdom seems to be that CAs present a single 179 | point of failure in the [X.509 Public Key Infrastructure][x509], 180 | due to the amount of trust placed in them; 181 | CA credentials have been stolen before, and used to forge 182 | certificates, showing the dangers to be very real. 183 | [^ch]: Jeff actually concludes that (emphasis mine): 184 | 185 | > We need to work toward making HTTPS easier, faster, 186 | > and most of all, the default for *logged in* users. 187 | 188 | but, for tiny sites with equally tiny hosting costs, why not extend 189 | the grace to everyone? 190 | 191 | 192 | 193 | 194 | 195 | [CSR]: http://en.wikipedia.org/wiki/Certificate_signing_request "Certificate Signing Request" 196 | [HttpSsl]: http://wiki.nginx.org/HttpSslModule 197 | [nginx https]: http://nginx.org/en/docs/http/configuring_https_servers.html 198 | [Gandi cert]: http://wiki.gandi.net/en/ssl/intermediate 199 | [lukasa]: https://lukasa.co.uk/2013/03/HTTPS_All_The_Things/ 200 | [HTTPS]: http://en.wikipedia.org/wiki/HTTP_Secure 201 | [benjeffrey.com]: https://benjeffrey.com 202 | [Gandi]: https://www.gandi.net/ 203 | [Gandi SSL]: https://www.gandi.net/domain/ssl 204 | [building]: https://benjeffrey.com/posts/building-benjeffrey.com-with-hakyll 205 | [verify]: https://www.gandi.net/ssl/secured/benjeffrey.com/30951/ccb4de3b85 206 | [Should All Web Traffic Be Encrypted?]: http://www.codinghorror.com/blog/2012/02/should-all-web-traffic-be-encrypted.html 207 | [CA]: http://en.wikipedia.org/wiki/Certificate_authority 208 | [x509]: http://en.wikipedia.org/wiki/X.509 209 | [ssl]: http://en.wikipedia.org/wiki/Secure_Sockets_Layer#Simple_TLS_handshake 210 | [nginx-conf]: https://github.com/jeffbr13/benjeffrey.com/blob/master/nginx 211 | [301]: http://en.wikipedia.org/wiki/HTTP_301 212 | -------------------------------------------------------------------------------- /posts/building-benjeffrey.com-with-hakyll.md: -------------------------------------------------------------------------------- 1 | --- 2 | title: Building benjeffrey.com with Hakyll 3 | description: How I build and deploy my website using Hakyll, the static-site generator written in Haskell. 4 | tags: web-development 5 | date: 2013-04-24 6 | --- 7 | 8 | A few weeks ago I finally bought the [benjeffrey.com][] domain name, 9 | which I've now moved to as my main presence on the 10 | WWW. So change your bookmarks 11 | and update your contacts, because [this is 12 | my new home][benjeffrey.com][^email]! 13 | 14 | After all, [benjeffrey.net][] was the first webpage I'd ever really put 15 | online (back when I was paying £10/year for [a domain name and shared 16 | hosting][fasthostingdirect]) and now my web presence was looking 17 | rather... meh. Certainly not the standard you'd expect from a student of 18 | Informatics! 19 | 20 | 21 | I wanted the following for my new web setup: 22 | 23 | * a static-site generator to build the content, because ~~that's what 24 | all the cool kids are doing~~ I liked the idea of my website 25 | being portable 26 | * a sensible way to deploy my website, whether that meant using 27 | a Git-based worklow, or simply `rsync`ing it (as I ended up doing) 28 | * the ability to write posts in [Pandoc Markdown][pandoc md] with all its 29 | fancy extensions; it supports LaTex expressions, as well as tables 30 | and footnotes, making fully-featured complex documents in Markdown 31 | a whole lot easier. 32 | 33 | I came across a cool little project by the name of [Hakyll][], while 34 | browsing the [Pandoc wiki][] looking for better content templates. 35 | 36 | Hakyll performs much the same function as [Jekyll][] and [similar static 37 | site generators][inspirations]. The primary difference between Hakyll and 38 | other software is that Hakyll is written in the functional programming 39 | language [Haskell][]. I wanted to ease this beautiful language in to my 40 | regular programming, since we spent the entire first semester learning it 41 | while getting to grips with Functional Programming, here at the 42 | University of Edinburgh. 43 | 44 | 45 | Customising Hakyll 46 | ------------------ 47 | 48 | ### Basic setup 49 | 50 | **Requirements:** GHC and [Cabal][], Haskell's package-management system. 51 | 52 | You should install Hakyll on your system through Cabal, so it can pull in 53 | its (many) dependencies, and then install the default Hakyll script into 54 | your (empty) website directory with `hakyll-init`[^cabal-scripts]: 55 | 56 | ```bash 57 | cabal install hakyll 58 | hakyll-init {directory} 59 | cd {directory} 60 | git init 61 | ``` 62 | 63 | My `.gitignore` file includes the following lines (alongside 64 | [GitHub's Haskell defaults][haskell-gi]) so as not to commit the files 65 | generated by Hakyll: 66 | 67 | ```bash 68 | # Hakyll compiled site 69 | _cache 70 | _site 71 | site 72 | hakyll 73 | ``` 74 | 75 | Next thing, I give script has a more descriptive name: 76 | 77 | ```bash 78 | mv site.hs hakyll.hs 79 | ``` 80 | 81 | One of the most interesting things about the Hakyll package is that it 82 | can be used more as a *library* of helpful functions, than a program per 83 | se. The Hakyll *script* installed in the directory by `hakyll-init` is a 84 | regular old Haskell source file which imports the Hakyll package and 85 | chains together various functions to describe [an I/O Action][hakyll 86 | main] which builds the static site! To generate the static site HTML, 87 | just compile the Haskell source and run the resulting executable's 88 | `build` command: 89 | 90 | ```bash 91 | ghc --make hakyll.hs 92 | ./hakyll build 93 | ``` 94 | 95 | [Hakyll's tutorials][hakyll-cmds] explain the various commands that the `hakyll` 96 | executable now provides. 97 | 98 | The following sections describe the various pieces of functionality in 99 | [my hakyll.hs][hakyll-source] which aren't included by 100 | default. 101 | 102 | ### Site Icon 103 | 104 | My site icon lives at `images/favicon.ico` before compilation. The 105 | following Hakyll rule copies it to `favicon.ico` in the compiled site 106 | directory: 107 | 108 | ```haskell 109 | main :: IO () 110 | main = hakyll $ do 111 | -- ... 112 | 113 | -- copy site icon to `favicon.ico` 114 | match "images/favicon.ico" $ do 115 | route (constRoute "favicon.ico") 116 | compile copyFileCompiler 117 | -- ... 118 | ``` 119 | 120 | As well as moving the ICO file, I also added 121 | 122 | ```html 123 | 124 | 125 | 126 | 127 | 128 | ``` 129 | 130 | into the [default template][]'s `head` element, just in case. To be 131 | honest, this really makes the Hakyll rule redundant, as I could set the 132 | `href` attribute to anything. But where'd be the fun in that? 133 | 134 | 135 | ### Copying Documents to the Web Root 136 | 137 | The following rule just ensures that the site [`robots.txt`](/robots.txt) 138 | and [`humans.txt`](/humans.txt) get copied into the web root (i.e. `/`): 139 | 140 | ```haskell 141 | -- copy humans.txt and robots.txt to web root 142 | match (fromList ["humans.txt", "robots.txt"]) $ do 143 | route idRoute 144 | compile copyFileCompiler 145 | ``` 146 | 147 | 148 | ### Compiling Documents to the Web Root with Pandoc 149 | 150 | I used to keep the location of my CV short by writing it as a raw HTML 151 | file, and keeping it in the document root of the webserver as `/cv`, 152 | stripping the file suffix. This required some Apache `.htaccess` rules 153 | for it to actually serve the file with the correct content-type, but it 154 | worked. But, as you can imagine, updating HTML by hand got pretty tiring, 155 | so I now write my CV as a Markdown file. 156 | 157 | So that my CV still lives at [/cv](/cv), I wrote a custom rule that 158 | places documents in the web root, after they've been compiled through 159 | Pandoc. 160 | 161 | The default Hakyll script has a rule for copying static files into the 162 | generated web root. I used the same rule, only replacing the 163 | `copyFileCompiler` with the `pandocCompiler`, then setting it to run 164 | through the necessary templates: 165 | 166 | ```haskell 167 | -- Compile static pages to web root with Pandoc 168 | match (fromList ["cv.md"]) $ do 169 | route $ setExtension "" 170 | compile $ pandocCompiler 171 | >>= loadAndApplyTemplate "templates/default.html" defaultContext 172 | >>= relativizeUrls 173 | ``` 174 | 175 | 176 | ### Compiling Sass/SCSS through Hakyll 177 | 178 | **Requirements:** [Sass][] and [Compass][] gems (installed systemwide). 179 | 180 | I decided to use Zurb's [Foundation web framework][foundation] on this 181 | site, as an experiment in "things which aren't Bootstrap". I have a bit 182 | of experience with Sass, and it's quite nice to be able to limit 183 | "div-itis" by using [Foundation's Sass mixin support][foundation-sass]! 184 | 185 | [Compass][] is a must for developing Sass stylesheets, collecting 186 | essential functions such as [sticky footers][] in one handy place, and 187 | is required by Foundation anyway. 188 | 189 | Luckily, rather than having `compass watch` constantly running when 190 | editing the Sass stylesheets, The Haddock docs for Hakyll [describe a rule 191 | for compiling SCSS to CSS][hakyll-scss] using the `unixFilter`. 192 | 193 | This next rule (based on the above) compiles matched the Sass stylesheets 194 | when you issue the Hakyll `build` command, but also tells the `sass` 195 | command to enable Compass and to compress the output: 196 | 197 | ```haskell 198 | match "scss/app.scss" $do 199 | route $ gsubRoute "scss/" (const "css/") `composeRoutes` setExtension "css" 200 | compile $ getResourceString 201 | >>= withItemBody (unixFilter "sass" ["-s", "--scss", "--compass", "--style", "compressed"]) 202 | >>= return . fmap compressCss 203 | ``` 204 | 205 | ### Removing URL Suffixes 206 | 207 | Wherever `setExtension` is used for HTML pages, I've fed it an empty 208 | string, so that webpages don't have the ugly `.html` suffix on the end. 209 | 210 | ```haskell 211 | match "post/*" $ do 212 | route $ setExtension "" 213 | compile $ pandocCompiler 214 | >>= loadAndApplyTemplate "templates/post.html" postCtx 215 | >>= loadAndApplyTemplate "templates/default.html" postCtx 216 | >>= relativizeUrls 217 | ``` 218 | 219 | Just in case, the templates include the following `meta` tag in the 220 | `head`, to ensure that each page is detected as HTML: 221 | 222 | ```html 223 | 224 | ``` 225 | 226 | 227 | Deploying with Hakyll 228 | --------------------- 229 | 230 | Hakyll has a great feature hidden away in its documentation: [the 231 | deployCommand][deploy command]. It turns out that you can specify an 232 | arbitrary command in the configuration for Hakyll to execute when you 233 | run: 234 | 235 | ```bash 236 | ./hakyll deploy 237 | ``` 238 | 239 | One might set this to execute a bash script, but since I just `rsync` the 240 | files up to my server (which is called `parsley` in my SSH config) I've 241 | put the entire command inside my Hakyll Configuration value, at the top 242 | of the script: 243 | 244 | ```haskell 245 | -------------------------------------------------------------------------------- 246 | config :: Configuration 247 | config = defaultConfiguration 248 | { deployCommand = "rsync -avz -e ssh ./_site/ parsley:/var/www/benjeffrey.com/"} 249 | 250 | -------------------------------------------------------------------------------- 251 | ``` 252 | 253 | Hakyll needs to be told to run with your new configuration, so you'll 254 | have to replace the `hakyll :: Rules a -> IO ()` function in the line 255 | 256 | ```haskell 257 | main = hakyll $ do 258 | ``` 259 | 260 | with the `hakyllWith :: Configuration -> Rules a -> IO ()` function. 261 | 262 | 263 | Summary 264 | ------- 265 | 266 | [benjeffrey.com][] is built and deployed (as of 267 | 2013-04) through a combination of: 268 | 269 | * Hakyll 270 | * Sass & Compass 271 | * Nginx 272 | * Git 273 | * SSH 274 | 275 | My final directory structure now looks something like: 276 | 277 | ``` 278 | {directory} 279 | |-- images 280 | \- ... 281 | |-- posts 282 | \- ... 283 | |-- scss 284 | |- app.scss 285 | |- ... 286 | |- foundation 287 | \ ... 288 | |-- templates 289 | \- ... 290 | |-- archive 291 | |-- config.rb (for Compass) 292 | |-- cv.md 293 | |-- hakyll.hs 294 | |-- hakyll 295 | |-- humans.txt 296 | |-- index.html 297 | |-- nginx 298 | |-- README.md 299 | \- robots.txt 300 | ``` 301 | 302 | with the whole site [available on GitHub][hakyll-gh]. 303 | 304 | 305 | 306 | 307 | 308 | [^email]: My email address will still be though. 309 | I'm still figuring out how to best add email to my new domain, 310 | or even if it's worth adding yet *another* email address to my 311 | collection! I may look into doing some sort of mail forwarding, 312 | either at the DNS or the mailbox level, at a later date. 313 | 314 | [^cabal-scripts]: If you can't run the `hakyll-init` command, you may 315 | need to add the local Cabal binary folder to your shell's `$PATH` 316 | variable with the following lines in your shell config: 317 | 318 | ```bash 319 | # The following goes into ~/.profile, ~/.zshrc, ~/.bashrc, or similar: 320 | 321 | # Cabal executables 322 | PATH=$PATH:$HOME/.cabal/bin 323 | ``` 324 | 325 | 326 | 327 | 328 | [benjeffrey.com]: http://benjeffrey.com 329 | [benjeffrey.net]: http://benjeffrey.net 330 | [fasthostingdirect]: http://www.fasthostingdirect.co.uk/ 331 | [Jekyll]: http://jekyllrb.com/ 332 | [Octopress]: http://octopress.org/ 333 | [GitHub Pages]: http://pages.github.com/ 334 | [Hakyll]: http://jaspervdj.be/hakyll/ 335 | [Hakyll tutorials]: http://jaspervdj.be/hakyll/tutorials.html 336 | [Hakyll reference]: http://jaspervdj.be/hakyll/reference/index.html 337 | [Bootstrap]: http://twitter.github.io/bootstrap/ 338 | [foundation]: http://foundation.zurb.com/ 339 | [Cabal]: http://www.haskell.org/cabal/ 340 | [INF-YT]: http://inf-yt.org.uk/ 341 | [daylerees]: http://daylerees.com/ 342 | [ST colour schemes]: https://github.com/daylerees/colour-schemes 343 | [COLOURlovers]: http://www.colourlovers.com/ 344 | [Pandoc wiki]: https://github.com/jgm/pandoc/wiki/Pandoc-Extras 345 | [pandoc md]: http://johnmacfarlane.net/pandoc/README.html#pandocs-markdown 346 | [haskell-gi]: https://github.com/github/gitignore/blob/master/Haskell.gitignore 347 | [hakyll-source]: https://github.com/jeffbr13/benjeffrey.com/blob/master/hakyll.hs 348 | [robots]: https://en.wikipedia.org/wiki/Robots_exclusion_standard 349 | [default template]: https://github.com/jeffbr13/benjeffrey.com/blob/master/templates/default.html 350 | [foundation-sass]: http://foundation.zurb.com/docs/sass.html 351 | [sticky footers]: http://compass-style.org/reference/compass/layout/sticky_footer/ 352 | [Michael Walker]: http://www.barrucadu.co.uk/ 353 | [Citation Needed]: http://citationneeded.me/ 354 | [Compass]: http://compass-style.org/ 355 | [Sass]: http://sass-lang.com/ 356 | [cn-scss]: http://citationneeded.me/hakyll.html#templates-css-static-and-wrapped-files 357 | [hakyll-scss]: http://jaspervdj.be/hakyll/reference/Hakyll-Core-UnixFilter.html 358 | [hakyll-cmds]: http://jaspervdj.be/hakyll/tutorials/02-basics.html 359 | [deploy command]: http://jaspervdj.be/hakyll/reference/Hakyll-Core-Configuration.html#v:deployCommand 360 | [hakyll-gh]: https://github.com/jeffbr13/benjeffrey.com/blob/master/hakyll.hs 361 | [inspirations]: http://jaspervdj.be/hakyll/about.html#inspiration 362 | [Haskell]: http://www.haskell.org/ 363 | [hakyll main]: http://jaspervdj.be/hakyll/reference/Hakyll-Main.html#v:hakyll 364 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Mozilla Public License Version 2.0 2 | ================================== 3 | 4 | 1. Definitions 5 | -------------- 6 | 7 | 1.1. "Contributor" 8 | means each individual or legal entity that creates, contributes to 9 | the creation of, or owns Covered Software. 10 | 11 | 1.2. "Contributor Version" 12 | means the combination of the Contributions of others (if any) used 13 | by a Contributor and that particular Contributor's Contribution. 14 | 15 | 1.3. "Contribution" 16 | means Covered Software of a particular Contributor. 17 | 18 | 1.4. "Covered Software" 19 | means Source Code Form to which the initial Contributor has attached 20 | the notice in Exhibit A, the Executable Form of such Source Code 21 | Form, and Modifications of such Source Code Form, in each case 22 | including portions thereof. 23 | 24 | 1.5. "Incompatible With Secondary Licenses" 25 | means 26 | 27 | (a) that the initial Contributor has attached the notice described 28 | in Exhibit B to the Covered Software; or 29 | 30 | (b) that the Covered Software was made available under the terms of 31 | version 1.1 or earlier of the License, but not also under the 32 | terms of a Secondary License. 33 | 34 | 1.6. "Executable Form" 35 | means any form of the work other than Source Code Form. 36 | 37 | 1.7. "Larger Work" 38 | means a work that combines Covered Software with other material, in 39 | a separate file or files, that is not Covered Software. 40 | 41 | 1.8. "License" 42 | means this document. 43 | 44 | 1.9. "Licensable" 45 | means having the right to grant, to the maximum extent possible, 46 | whether at the time of the initial grant or subsequently, any and 47 | all of the rights conveyed by this License. 48 | 49 | 1.10. "Modifications" 50 | means any of the following: 51 | 52 | (a) any file in Source Code Form that results from an addition to, 53 | deletion from, or modification of the contents of Covered 54 | Software; or 55 | 56 | (b) any new file in Source Code Form that contains any Covered 57 | Software. 58 | 59 | 1.11. "Patent Claims" of a Contributor 60 | means any patent claim(s), including without limitation, method, 61 | process, and apparatus claims, in any patent Licensable by such 62 | Contributor that would be infringed, but for the grant of the 63 | License, by the making, using, selling, offering for sale, having 64 | made, import, or transfer of either its Contributions or its 65 | Contributor Version. 66 | 67 | 1.12. "Secondary License" 68 | means either the GNU General Public License, Version 2.0, the GNU 69 | Lesser General Public License, Version 2.1, the GNU Affero General 70 | Public License, Version 3.0, or any later versions of those 71 | licenses. 72 | 73 | 1.13. "Source Code Form" 74 | means the form of the work preferred for making modifications. 75 | 76 | 1.14. "You" (or "Your") 77 | means an individual or a legal entity exercising rights under this 78 | License. For legal entities, "You" includes any entity that 79 | controls, is controlled by, or is under common control with You. For 80 | purposes of this definition, "control" means (a) the power, direct 81 | or indirect, to cause the direction or management of such entity, 82 | whether by contract or otherwise, or (b) ownership of more than 83 | fifty percent (50%) of the outstanding shares or beneficial 84 | ownership of such entity. 85 | 86 | 2. License Grants and Conditions 87 | -------------------------------- 88 | 89 | 2.1. Grants 90 | 91 | Each Contributor hereby grants You a world-wide, royalty-free, 92 | non-exclusive license: 93 | 94 | (a) under intellectual property rights (other than patent or trademark) 95 | Licensable by such Contributor to use, reproduce, make available, 96 | modify, display, perform, distribute, and otherwise exploit its 97 | Contributions, either on an unmodified basis, with Modifications, or 98 | as part of a Larger Work; and 99 | 100 | (b) under Patent Claims of such Contributor to make, use, sell, offer 101 | for sale, have made, import, and otherwise transfer either its 102 | Contributions or its Contributor Version. 103 | 104 | 2.2. Effective Date 105 | 106 | The licenses granted in Section 2.1 with respect to any Contribution 107 | become effective for each Contribution on the date the Contributor first 108 | distributes such Contribution. 109 | 110 | 2.3. Limitations on Grant Scope 111 | 112 | The licenses granted in this Section 2 are the only rights granted under 113 | this License. No additional rights or licenses will be implied from the 114 | distribution or licensing of Covered Software under this License. 115 | Notwithstanding Section 2.1(b) above, no patent license is granted by a 116 | Contributor: 117 | 118 | (a) for any code that a Contributor has removed from Covered Software; 119 | or 120 | 121 | (b) for infringements caused by: (i) Your and any other third party's 122 | modifications of Covered Software, or (ii) the combination of its 123 | Contributions with other software (except as part of its Contributor 124 | Version); or 125 | 126 | (c) under Patent Claims infringed by Covered Software in the absence of 127 | its Contributions. 128 | 129 | This License does not grant any rights in the trademarks, service marks, 130 | or logos of any Contributor (except as may be necessary to comply with 131 | the notice requirements in Section 3.4). 132 | 133 | 2.4. Subsequent Licenses 134 | 135 | No Contributor makes additional grants as a result of Your choice to 136 | distribute the Covered Software under a subsequent version of this 137 | License (see Section 10.2) or under the terms of a Secondary License (if 138 | permitted under the terms of Section 3.3). 139 | 140 | 2.5. Representation 141 | 142 | Each Contributor represents that the Contributor believes its 143 | Contributions are its original creation(s) or it has sufficient rights 144 | to grant the rights to its Contributions conveyed by this License. 145 | 146 | 2.6. Fair Use 147 | 148 | This License is not intended to limit any rights You have under 149 | applicable copyright doctrines of fair use, fair dealing, or other 150 | equivalents. 151 | 152 | 2.7. Conditions 153 | 154 | Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted 155 | in Section 2.1. 156 | 157 | 3. Responsibilities 158 | ------------------- 159 | 160 | 3.1. Distribution of Source Form 161 | 162 | All distribution of Covered Software in Source Code Form, including any 163 | Modifications that You create or to which You contribute, must be under 164 | the terms of this License. You must inform recipients that the Source 165 | Code Form of the Covered Software is governed by the terms of this 166 | License, and how they can obtain a copy of this License. You may not 167 | attempt to alter or restrict the recipients' rights in the Source Code 168 | Form. 169 | 170 | 3.2. Distribution of Executable Form 171 | 172 | If You distribute Covered Software in Executable Form then: 173 | 174 | (a) such Covered Software must also be made available in Source Code 175 | Form, as described in Section 3.1, and You must inform recipients of 176 | the Executable Form how they can obtain a copy of such Source Code 177 | Form by reasonable means in a timely manner, at a charge no more 178 | than the cost of distribution to the recipient; and 179 | 180 | (b) You may distribute such Executable Form under the terms of this 181 | License, or sublicense it under different terms, provided that the 182 | license for the Executable Form does not attempt to limit or alter 183 | the recipients' rights in the Source Code Form under this License. 184 | 185 | 3.3. Distribution of a Larger Work 186 | 187 | You may create and distribute a Larger Work under terms of Your choice, 188 | provided that You also comply with the requirements of this License for 189 | the Covered Software. If the Larger Work is a combination of Covered 190 | Software with a work governed by one or more Secondary Licenses, and the 191 | Covered Software is not Incompatible With Secondary Licenses, this 192 | License permits You to additionally distribute such Covered Software 193 | under the terms of such Secondary License(s), so that the recipient of 194 | the Larger Work may, at their option, further distribute the Covered 195 | Software under the terms of either this License or such Secondary 196 | License(s). 197 | 198 | 3.4. Notices 199 | 200 | You may not remove or alter the substance of any license notices 201 | (including copyright notices, patent notices, disclaimers of warranty, 202 | or limitations of liability) contained within the Source Code Form of 203 | the Covered Software, except that You may alter any license notices to 204 | the extent required to remedy known factual inaccuracies. 205 | 206 | 3.5. Application of Additional Terms 207 | 208 | You may choose to offer, and to charge a fee for, warranty, support, 209 | indemnity or liability obligations to one or more recipients of Covered 210 | Software. However, You may do so only on Your own behalf, and not on 211 | behalf of any Contributor. You must make it absolutely clear that any 212 | such warranty, support, indemnity, or liability obligation is offered by 213 | You alone, and You hereby agree to indemnify every Contributor for any 214 | liability incurred by such Contributor as a result of warranty, support, 215 | indemnity or liability terms You offer. You may include additional 216 | disclaimers of warranty and limitations of liability specific to any 217 | jurisdiction. 218 | 219 | 4. Inability to Comply Due to Statute or Regulation 220 | --------------------------------------------------- 221 | 222 | If it is impossible for You to comply with any of the terms of this 223 | License with respect to some or all of the Covered Software due to 224 | statute, judicial order, or regulation then You must: (a) comply with 225 | the terms of this License to the maximum extent possible; and (b) 226 | describe the limitations and the code they affect. Such description must 227 | be placed in a text file included with all distributions of the Covered 228 | Software under this License. Except to the extent prohibited by statute 229 | or regulation, such description must be sufficiently detailed for a 230 | recipient of ordinary skill to be able to understand it. 231 | 232 | 5. Termination 233 | -------------- 234 | 235 | 5.1. The rights granted under this License will terminate automatically 236 | if You fail to comply with any of its terms. However, if You become 237 | compliant, then the rights granted under this License from a particular 238 | Contributor are reinstated (a) provisionally, unless and until such 239 | Contributor explicitly and finally terminates Your grants, and (b) on an 240 | ongoing basis, if such Contributor fails to notify You of the 241 | non-compliance by some reasonable means prior to 60 days after You have 242 | come back into compliance. Moreover, Your grants from a particular 243 | Contributor are reinstated on an ongoing basis if such Contributor 244 | notifies You of the non-compliance by some reasonable means, this is the 245 | first time You have received notice of non-compliance with this License 246 | from such Contributor, and You become compliant prior to 30 days after 247 | Your receipt of the notice. 248 | 249 | 5.2. If You initiate litigation against any entity by asserting a patent 250 | infringement claim (excluding declaratory judgment actions, 251 | counter-claims, and cross-claims) alleging that a Contributor Version 252 | directly or indirectly infringes any patent, then the rights granted to 253 | You by any and all Contributors for the Covered Software under Section 254 | 2.1 of this License shall terminate. 255 | 256 | 5.3. In the event of termination under Sections 5.1 or 5.2 above, all 257 | end user license agreements (excluding distributors and resellers) which 258 | have been validly granted by You or Your distributors under this License 259 | prior to termination shall survive termination. 260 | 261 | ************************************************************************ 262 | * * 263 | * 6. Disclaimer of Warranty * 264 | * ------------------------- * 265 | * * 266 | * Covered Software is provided under this License on an "as is" * 267 | * basis, without warranty of any kind, either expressed, implied, or * 268 | * statutory, including, without limitation, warranties that the * 269 | * Covered Software is free of defects, merchantable, fit for a * 270 | * particular purpose or non-infringing. The entire risk as to the * 271 | * quality and performance of the Covered Software is with You. * 272 | * Should any Covered Software prove defective in any respect, You * 273 | * (not any Contributor) assume the cost of any necessary servicing, * 274 | * repair, or correction. This disclaimer of warranty constitutes an * 275 | * essential part of this License. No use of any Covered Software is * 276 | * authorized under this License except under this disclaimer. * 277 | * * 278 | ************************************************************************ 279 | 280 | ************************************************************************ 281 | * * 282 | * 7. Limitation of Liability * 283 | * -------------------------- * 284 | * * 285 | * Under no circumstances and under no legal theory, whether tort * 286 | * (including negligence), contract, or otherwise, shall any * 287 | * Contributor, or anyone who distributes Covered Software as * 288 | * permitted above, be liable to You for any direct, indirect, * 289 | * special, incidental, or consequential damages of any character * 290 | * including, without limitation, damages for lost profits, loss of * 291 | * goodwill, work stoppage, computer failure or malfunction, or any * 292 | * and all other commercial damages or losses, even if such party * 293 | * shall have been informed of the possibility of such damages. This * 294 | * limitation of liability shall not apply to liability for death or * 295 | * personal injury resulting from such party's negligence to the * 296 | * extent applicable law prohibits such limitation. Some * 297 | * jurisdictions do not allow the exclusion or limitation of * 298 | * incidental or consequential damages, so this exclusion and * 299 | * limitation may not apply to You. * 300 | * * 301 | ************************************************************************ 302 | 303 | 8. Litigation 304 | ------------- 305 | 306 | Any litigation relating to this License may be brought only in the 307 | courts of a jurisdiction where the defendant maintains its principal 308 | place of business and such litigation shall be governed by laws of that 309 | jurisdiction, without reference to its conflict-of-law provisions. 310 | Nothing in this Section shall prevent a party's ability to bring 311 | cross-claims or counter-claims. 312 | 313 | 9. Miscellaneous 314 | ---------------- 315 | 316 | This License represents the complete agreement concerning the subject 317 | matter hereof. If any provision of this License is held to be 318 | unenforceable, such provision shall be reformed only to the extent 319 | necessary to make it enforceable. Any law or regulation which provides 320 | that the language of a contract shall be construed against the drafter 321 | shall not be used to construe this License against a Contributor. 322 | 323 | 10. Versions of the License 324 | --------------------------- 325 | 326 | 10.1. New Versions 327 | 328 | Mozilla Foundation is the license steward. Except as provided in Section 329 | 10.3, no one other than the license steward has the right to modify or 330 | publish new versions of this License. Each version will be given a 331 | distinguishing version number. 332 | 333 | 10.2. Effect of New Versions 334 | 335 | You may distribute the Covered Software under the terms of the version 336 | of the License under which You originally received the Covered Software, 337 | or under the terms of any subsequent version published by the license 338 | steward. 339 | 340 | 10.3. Modified Versions 341 | 342 | If you create software not governed by this License, and you want to 343 | create a new license for such software, you may create and use a 344 | modified version of this License if you rename the license and remove 345 | any references to the name of the license steward (except to note that 346 | such modified license differs from this License). 347 | 348 | 10.4. Distributing Source Code Form that is Incompatible With Secondary 349 | Licenses 350 | 351 | If You choose to distribute Source Code Form that is Incompatible With 352 | Secondary Licenses under the terms of this version of the License, the 353 | notice described in Exhibit B of this License must be attached. 354 | 355 | Exhibit A - Source Code Form License Notice 356 | ------------------------------------------- 357 | 358 | This Source Code Form is subject to the terms of the Mozilla Public 359 | License, v. 2.0. If a copy of the MPL was not distributed with this 360 | file, You can obtain one at http://mozilla.org/MPL/2.0/. 361 | 362 | If it is not possible or desirable to put the notice in a particular 363 | file, then You may include the notice in a location (such as a LICENSE 364 | file in a relevant directory) where a recipient would be likely to look 365 | for such a notice. 366 | 367 | You may add additional accurate notices of copyright ownership. 368 | 369 | Exhibit B - "Incompatible With Secondary Licenses" Notice 370 | --------------------------------------------------------- 371 | 372 | This Source Code Form is "Incompatible With Secondary Licenses", as 373 | defined by the Mozilla Public License, v. 2.0. 374 | -------------------------------------------------------------------------------- /content/mail@benjeffrey.com.asc: -------------------------------------------------------------------------------- 1 | -----BEGIN PGP PUBLIC KEY BLOCK----- 2 | Version: GnuPG/MacGPG2 v2.0.20 (Darwin) 3 | 4 | mQINBFIp8/gBEADDiCp9uH/PRO9modIZCiFMcMSbaMNe599g625c5KFpJDJcxjxw 5 | 1JWQinxj75/tVooZb6v1VzydI3QRLqFDxdEJjLSmgFcz/x6IXWGc7wXSPCIC3Fk9 6 | uja7tVI6lWddB1L5VXIjWhag/70zyiC58qa4WVDyvggWYjrOZccryHIqShwV2uHA 7 | Sl15Ce1BF25ULDT+R3eOfhzPHlutc/sh1Lj87Y4afxQpFU4WLncYm+A1em18x/UB 8 | 53N7QTbwuJBSzutErNzsl3s8R5qn6cqVfqDIA2TiB3mNi6DUA2lT0HOyaa9oP1dM 9 | gVc7V9yqU7EQu1ZTDRQCxcFUEHDMmNpN0+0Yv8QEK/lG05XYf1oP8iKdt0FklTyX 10 | CgcQvD5yXx9BNYXyL3f08jBacYm/NzjpZyrctW5l0mT+g0r4zUYhyerV1MxweE4/ 11 | VyyQwkkk59iuyBJZRZ7pAjaO/LTRv5KA1fkNAwdPDOwNfRIW7eAGODlbcF6uFcI7 12 | XUcLCXp+dHJdilJzPn+I5wdB6vidfnBdNt+T3hEP2oE9t092U8hteUeo9jKs8QOb 13 | 1nbzJtYF7tr43FHm3vcOxVLfN+GdouZti5htnQ7ydZfs7fYAdc78xxQ68/kCB9fq 14 | r8seT3OgvK0fTK6Vvr1NJUVh+UewlE6nAmGLzXv1bUnoxkrB4k+UZAJuXwARAQAB 15 | tCFCZW4gSmVmZnJleSA8bWFpbEBiZW5qZWZmcmV5LmNvbT6JAj0EEwEKACcFAlIp 16 | 8/gCGy8FCQeGH4AFCwkIBwMFFQoJCAsFFgIDAQACHgECF4AACgkQMtvEt66nP7Ys 17 | eg//TBUDt3iDx2Lswj30xiemA6wFdPQZKgbVZlB7eba2H6lVeQQSA0WZ6aMFP/NL 18 | aq849IW3qubFWTme/AYhuhjZFNQBU+iB1WuX/TMxj3xXbfDXAFTVPN0lRdrXXeUd 19 | YN0oZgX+feCd33Mi3f/ZY7PggkQSAXeENppDboYbvofKHfvsZXeGncgtt79RF9Yh 20 | vv2fU9GDurKEVhlu30df4raT9DFm2F4zSVCRDyL7VtrLlsLvienbOgz3s2ZUB/Jo 21 | 0TM0uuF2t9c2rJnZRM4dqm/C5f+QZTQWojDJ1v/QHyRJF2izwTlegDDQnzU+VqyM 22 | spWCtmaX0uN2odlnVnEu2ICTLXU8nT2PIzJkqpspWTixH2zWGFTLuwZfbryQ62Zq 23 | XUq3z0OvlGUea/3FCMJ06s2ZKKR3JwpGmAVbjTbDe5uH8CG5+8MNL/YO216yAaIR 24 | tpCKDhFREDrsTSAO8MCrSjkTdSJhtNMu/umnAHfkAmGnp8xGv4nTWReI3dbbBERE 25 | if/ItMUdEXs2G4aOwAu8RRRk8RoijOQ9Nko4vpViMsqYGbTFy4bSFQbCdXxS3mSK 26 | ASxEuq97Zaut0oH6DRP4UE4bxUvatou6e1MY3zigruCCUFTCZ4FP2BhYBKb2jQ3l 27 | tJeV+pBzhLgS5cYjkB6dLfGFD2CHFhW0/P6b2pw/AWGQ5G7R/wAARpX/AABGkAEQ 28 | AAEBAAAAAAAAAAAAAAAA/9j/4AAQSkZJRgABAQEASABIAAD/4QGKRXhpZgAASUkq 29 | AAgAAAAKAA8BAgAEAAAATEdFABABAgAIAAAAhgAAABIBAwABAAAAAQAAABoBBQAB 30 | AAAAjgAAABsBBQABAAAAlgAAACgBAwABAAAAAgAAADEBAgALAAAAngAAADIBAgAU 31 | AAAAqgAAAGmHBAABAAAAvgAAACWIBAABAAAAQAEAAAAAAABOZXh1cyA0AEgAAAAB 32 | AAAASAAAAAEAAABHSU1QIDIuOC40AAAyMDEzOjA5OjA5IDE1OjM5OjI0AAcAAJAH 33 | AAQAAAAwMjEwA5ACABQAAAAYAQAABJACABQAAAAsAQAAAKAHAAQAAAAwMTAwAaAD 34 | AAEAAAD//wAAAqAJAAEAAADwAAAAA6AJAAEAAAAgAQAAAAAAADIwMTM6MDY6MTEg 35 | MjM6MTY6MjAAMjAxMzowNjoxMSAyMzoxNjoyMAADAAEAAgACAAAATgAAAAIABQAD 36 | AAAAagEAABsABwABAAAAAAAAAAAAAAA3AAAAAQAAADoAAAABAAAAdBQAABAnAAD/ 37 | 4QvdaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLwA8P3hwYWNrZXQgYmVnaW49 38 | J++7vycgaWQ9J1c1TTBNcENlaGlIenJlU3pOVGN6a2M5ZCc/Pgo8eDp4bXBtZXRh 39 | IHhtbG5zOng9J2Fkb2JlOm5zOm1ldGEvJz4KPHJkZjpSREYgeG1sbnM6cmRmPSdo 40 | dHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjJz4KCiA8 41 | cmRmOkRlc2NyaXB0aW9uIHhtbG5zOmV4aWY9J2h0dHA6Ly9ucy5hZG9iZS5jb20v 42 | ZXhpZi8xLjAvJz4KICA8ZXhpZjpJbWFnZVdpZHRoPjE4NTI8L2V4aWY6SW1hZ2VX 43 | aWR0aD4KICA8ZXhpZjpJbWFnZUxlbmd0aD4xODUyPC9leGlmOkltYWdlTGVuZ3Ro 44 | PgogIDxleGlmOk1ha2U+TEdFPC9leGlmOk1ha2U+CiAgPGV4aWY6TW9kZWw+TmV4 45 | dXMgNDwvZXhpZjpNb2RlbD4KICA8ZXhpZjpPcmllbnRhdGlvbj5Ub3AtbGVmdDwv 46 | ZXhpZjpPcmllbnRhdGlvbj4KICA8ZXhpZjpYUmVzb2x1dGlvbj43MjwvZXhpZjpY 47 | UmVzb2x1dGlvbj4KICA8ZXhpZjpZUmVzb2x1dGlvbj43MjwvZXhpZjpZUmVzb2x1 48 | dGlvbj4KICA8ZXhpZjpSZXNvbHV0aW9uVW5pdD5JbmNoPC9leGlmOlJlc29sdXRp 49 | b25Vbml0PgogIDxleGlmOlNvZnR3YXJlPlNob3R3ZWxsIDAuMTQuMTwvZXhpZjpT 50 | b2Z0d2FyZT4KICA8ZXhpZjpEYXRlVGltZT4yMDEzOjA2OjExIDIzOjE2OjIwPC9l 51 | eGlmOkRhdGVUaW1lPgogIDxleGlmOkZsYXNoUGl4VmVyc2lvbj5GbGFzaFBpeCBW 52 | ZXJzaW9uIDEuMDwvZXhpZjpGbGFzaFBpeFZlcnNpb24+CiAgPGV4aWY6SW50ZXJv 53 | cGVyYWJpbGl0eUluZGV4Pk48L2V4aWY6SW50ZXJvcGVyYWJpbGl0eUluZGV4Pgog 54 | IDxleGlmOkludGVyb3BlcmFiaWxpdHlWZXJzaW9uPjU1LCA1OCwgMC41MjM2PC9l 55 | eGlmOkludGVyb3BlcmFiaWxpdHlWZXJzaW9uPgogIDxleGlmOk1ha2U+TEdFPC9l 56 | eGlmOk1ha2U+CiAgPGV4aWY6TW9kZWw+TmV4dXMgNDwvZXhpZjpNb2RlbD4KICA8 57 | ZXhpZjpPcmllbnRhdGlvbj5Ub3AtbGVmdDwvZXhpZjpPcmllbnRhdGlvbj4KICA8 58 | ZXhpZjpYUmVzb2x1dGlvbj43MjwvZXhpZjpYUmVzb2x1dGlvbj4KICA8ZXhpZjpZ 59 | UmVzb2x1dGlvbj43MjwvZXhpZjpZUmVzb2x1dGlvbj4KICA8ZXhpZjpSZXNvbHV0 60 | aW9uVW5pdD5JbmNoPC9leGlmOlJlc29sdXRpb25Vbml0PgogIDxleGlmOlNvZnR3 61 | YXJlPkdJTVAgMi44LjQ8L2V4aWY6U29mdHdhcmU+CiAgPGV4aWY6RGF0ZVRpbWU+ 62 | MjAxMzowNjoxMSAyMzo1MTo0MzwvZXhpZjpEYXRlVGltZT4KICA8ZXhpZjpGbGFz 63 | aFBpeFZlcnNpb24+Rmxhc2hQaXggVmVyc2lvbiAxLjA8L2V4aWY6Rmxhc2hQaXhW 64 | ZXJzaW9uPgogIDxleGlmOkludGVyb3BlcmFiaWxpdHlJbmRleD5OPC9leGlmOklu 65 | dGVyb3BlcmFiaWxpdHlJbmRleD4KICA8ZXhpZjpJbnRlcm9wZXJhYmlsaXR5VmVy 66 | c2lvbj41NSwgNTgsIDAuNTIzNjwvZXhpZjpJbnRlcm9wZXJhYmlsaXR5VmVyc2lv 67 | bj4KICA8ZXhpZjpJbWFnZVdpZHRoPjE4NTI8L2V4aWY6SW1hZ2VXaWR0aD4KICA8 68 | ZXhpZjpJbWFnZUxlbmd0aD4xODUyPC9leGlmOkltYWdlTGVuZ3RoPgogIDxleGlm 69 | Ok1ha2U+TEdFPC9leGlmOk1ha2U+CiAgPGV4aWY6TW9kZWw+TmV4dXMgNDwvZXhp 70 | ZjpNb2RlbD4KICA8ZXhpZjpPcmllbnRhdGlvbj5Ub3AtbGVmdDwvZXhpZjpPcmll 71 | bnRhdGlvbj4KICA8ZXhpZjpYUmVzb2x1dGlvbj43MjwvZXhpZjpYUmVzb2x1dGlv 72 | bj4KICA8ZXhpZjpZUmVzb2x1dGlvbj43MjwvZXhpZjpZUmVzb2x1dGlvbj4KICA8 73 | ZXhpZjpSZXNvbHV0aW9uVW5pdD5JbmNoPC9leGlmOlJlc29sdXRpb25Vbml0Pgog 74 | IDxleGlmOlNvZnR3YXJlPlNob3R3ZWxsIDAuMTQuMTwvZXhpZjpTb2Z0d2FyZT4K 75 | ICA8ZXhpZjpEYXRlVGltZT4yMDEzOjA2OjExIDIzOjE2OjIwPC9leGlmOkRhdGVU 76 | aW1lPgogIDxleGlmOkV4aWZWZXJzaW9uPkV4aWYgVmVyc2lvbiAyLjE8L2V4aWY6 77 | RXhpZlZlcnNpb24+CiAgPGV4aWY6Rmxhc2hQaXhWZXJzaW9uPkZsYXNoUGl4IFZl 78 | cnNpb24gMS4wPC9leGlmOkZsYXNoUGl4VmVyc2lvbj4KICA8ZXhpZjpDb2xvclNw 79 | YWNlPkludGVybmFsIGVycm9yICh1bmtub3duIHZhbHVlIDY1NTM1KTwvZXhpZjpD 80 | b2xvclNwYWNlPgogIDxleGlmOkludGVyb3BlcmFiaWxpdHlJbmRleD5OPC9leGlm 81 | OkludGVyb3BlcmFiaWxpdHlJbmRleD4KICA8ZXhpZjpJbnRlcm9wZXJhYmlsaXR5 82 | VmVyc2lvbj41NSwgNTgsIDAuNTIzNjwvZXhpZjpJbnRlcm9wZXJhYmlsaXR5VmVy 83 | c2lvbj4KICA8ZXhpZjpHUFNQcm9jZXNzaW5nTWV0aG9kPjEgYnl0ZXMgdW5kZWZp 84 | bmVkIGRhdGE8L2V4aWY6R1BTUHJvY2Vzc2luZ01ldGhvZD4KICA8ZXhpZjpEYXRl 85 | VGltZU9yaWdpbmFsPjIwMTMtMDYtMTFUMjI6MTY6MjBaPC9leGlmOkRhdGVUaW1l 86 | T3JpZ2luYWw+CiAgPGV4aWY6RGF0ZVRpbWVEaWdpdGl6ZWQ+MjAxMy0wNi0xMVQy 87 | MjoxNjoyMFo8L2V4aWY6RGF0ZVRpbWVEaWdpdGl6ZWQ+CiAgPGV4aWY6UGl4ZWxY 88 | RGltZW5zaW9uPjE4NTI8L2V4aWY6UGl4ZWxYRGltZW5zaW9uPgogIDxleGlmOlBp 89 | eGVsWURpbWVuc2lvbj4xODUyPC9leGlmOlBpeGVsWURpbWVuc2lvbj4KIDwvcmRm 90 | OkRlc2NyaXB0aW9uPgoKIDxyZGY6RGVzY3JpcHRpb24geG1sbnM6eG1wPSdodHRw 91 | Oi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvJz4KICA8eG1wOkNyZWF0ZURhdGU+MjAx 92 | My0wNi0xMVQyMjoxNjoyMFo8L3htcDpDcmVhdGVEYXRlPgogPC9yZGY6RGVzY3Jp 93 | cHRpb24+CgogPHJkZjpEZXNjcmlwdGlvbiB4bWxuczp0aWZmPSdodHRwOi8vbnMu 94 | YWRvYmUuY29tL3RpZmYvMS4wLyc+CiAgPHRpZmY6SW1hZ2VIZWlnaHQ+MTg1Mjwv 95 | dGlmZjpJbWFnZUhlaWdodD4KICA8dGlmZjpJbWFnZUhlaWdodD4xODUyPC90aWZm 96 | OkltYWdlSGVpZ2h0PgogIDx0aWZmOkltYWdlSGVpZ2h0PjE4NTI8L3RpZmY6SW1h 97 | Z2VIZWlnaHQ+CiAgPHRpZmY6SW1hZ2VXaWR0aD4xPC90aWZmOkltYWdlV2lkdGg+ 98 | CiAgPHRpZmY6SW1hZ2VIZWlnaHQ+MTg1MjwvdGlmZjpJbWFnZUhlaWdodD4KIDwv 99 | cmRmOkRlc2NyaXB0aW9uPgoKPC9yZGY6UkRGPgo8L3g6eG1wbWV0YT4KPD94cGFj 100 | a2V0IGVuZD0ncic/Pgr/2wBDAAgGBgcGBQgHBwcJCQgKDBQNDAsLDBkSEw8UHRof 101 | Hh0aHBwgJC4nICIsIxwcKDcpLDAxNDQ0Hyc5PTgyPC4zNDL/2wBDAQkJCQwLDBgN 102 | DRgyIRwhMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIyMjIy 103 | MjIyMjIyMjL/wgARCAEgAPADAREAAhEBAxEB/8QAGwAAAQUBAQAAAAAAAAAAAAAA 104 | BAACAwUGAQf/xAAZAQADAQEBAAAAAAAAAAAAAAAAAQIDBAX/2gAMAwEAAhADEAAA 105 | AdRNdBCHmqHHcF0SKuHC1W3DgkGyk1E00bFQ0dR1Eyo+8rnTKzqENBwEHA4hMmSQ 106 | IM/hvWrQxyxtJAp1lyBpE42ojYgOi3JxVPE4xkCa1Y1GpIsKng+Ag4HAmSQDRWVx 107 | 6AafUDssUPYhU+kCMmAdymTJmRYw+uY2o2GxQmmQ9xq8r1lw4EHA4iYXApMN80tA 108 | 7l7B2jcra1M0HahqWhGJjThyxcs11pByjqZCiu1yEudNne3cuDgIJUh4rF5dAFpr 109 | UNJgiIuxipwGuai4hpTy5Vb0yJolEA2ua+545MljXF25zdzsM71DhM4iYmJVgceg 110 | DSYmugh9TKlyAgEpTJnzUg5JZrRAgFTRVzYV5Rish3LntTi7nX5vT1PGSqeI89z6 111 | au560RNSTTkSS1Ta1NLOTJaewoUoMHAm0AU6e5lcXbUMmm0x8/V6Zzf1PE5Sc5N4 112 | 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 450 | R9I71O4= 451 | =YUUP 452 | -----END PGP PUBLIC KEY BLOCK----- 453 | --------------------------------------------------------------------------------