summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLuke Shumaker <LukeShu@sbcglobal.net>2013-10-12 13:47:42 -0400
committerLuke Shumaker <LukeShu@sbcglobal.net>2013-10-12 13:47:42 -0400
commit6a42c8de66e3b2dc7293ddeadaa3ee396db2624d (patch)
tree67a027b892d3122662526504dd6d11e8dea02ca1
initial commit
-rw-r--r--.gitignore1
-rw-r--r--Makefile14
-rwxr-xr-xindex.rb22
-rwxr-xr-xpagerender.rb37
-rw-r--r--public/arch-systemd.md56
-rw-r--r--public/assets/style.css48
-rw-r--r--public/bash-arrays.md201
-rw-r--r--public/emacs-as-an-os.md39
-rw-r--r--public/emacs-shells.md63
-rw-r--r--public/fd_printf.md37
-rw-r--r--public/fs-licensing-explanation.md62
-rw-r--r--public/git-go-pre-commit.md54
-rw-r--r--public/pacman-overview.md48
-rw-r--r--public/poor-system-documentation.md38
-rw-r--r--public/term-colors.md40
-rw-r--r--template.erb20
16 files changed, 780 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d65bd98
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+public/*.html
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..4255c4d
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,14 @@
+articles = $(patsubst %.md,%,$(wildcard public/*.md))
+
+.SECONDARY:
+
+all: public/index.html $(addsuffix .html,$(articles)) $(addsuffix .raw.html,$(articles))
+
+public/%.raw.html: public/%.md Makefile
+ rdiscount $< > $@
+public/%.html: public/%.md pagerender.rb template.erb Makefile
+ ./pagerender.rb $< > $@
+public/index.html: $(addsuffix .md,$(articles)) index.rb template.erb Makefile
+ ./index.rb $(sort $(filter-out Makefile index.rb template.erb,$^)) > $@
+clean:
+ rm -- public/*.html
diff --git a/index.rb b/index.rb
new file mode 100755
index 0000000..60b041a
--- /dev/null
+++ b/index.rb
@@ -0,0 +1,22 @@
+#!/usr/bin/env ruby
+# -*- coding: utf-8 -*-
+require 'erb'
+
+@title = "Web log entries"
+@copyright = "Luke Shumaker"
+license = "CC BY-SA-3.0"
+license_url = 'https://creativecommons.org/licenses/by-sa/3.0/'
+@license="<a href=\"#{license_url}\">#{license}</a>"
+
+@content = "<h1>#{@title}</h1>\n<ul>\n"
+for filename in ARGV do
+ title = File.read(filename).split("\n",2).first;
+ url=filename.sub(/^public\//,'./').sub(/\.md$/,'');
+ @content += "<li><tt><a href='#{url}.html'>#{url}</a></tt> — #{title}</a></li>\n"
+end
+@content += "</ul>\n"
+
+template = 'template.erb'
+erb = ERB.new(File.read(template));
+erb.filename = template
+erb.run()
diff --git a/pagerender.rb b/pagerender.rb
new file mode 100755
index 0000000..4e6f887
--- /dev/null
+++ b/pagerender.rb
@@ -0,0 +1,37 @@
+#!/usr/bin/env ruby
+require 'rdiscount'
+require 'erb'
+
+license_urls = {
+ "CC BY-SA-3.0" => 'https://creativecommons.org/licenses/by-sa/3.0/',
+ 'WTFPL-2' => "http://www.wtfpl.net/txt/copying/",
+}
+
+template = 'template.erb'
+input = ARGV.first
+
+lines = File.read(input).split("\n")
+
+markdown = ''
+tags = {}
+for line in lines do
+ if (line =~ /^:/)
+ (key, val) = line.sub(/^:/, '').split(/\s+/, 2)
+ tags[key] = val
+ else
+ markdown += "\n"+line
+ end
+end
+
+@title = tags['title'] || lines.first
+@copyright = tags['copyright'] || "Luke Shumaker"
+@license = tags['license'] || "CC BY-SA-3.0"
+unless license_urls[@license].nil?
+ @license="<a href=\"#{license_urls[@license]}\">#{@license}</a>"
+end
+
+@content = RDiscount.new(markdown).to_html
+
+erb = ERB.new(File.read(template));
+erb.filename = template
+erb.run()
diff --git a/public/arch-systemd.md b/public/arch-systemd.md
new file mode 100644
index 0000000..c3b9b37
--- /dev/null
+++ b/public/arch-systemd.md
@@ -0,0 +1,56 @@
+What Arch Linux's switch to systemd means for users
+===================================================
+:copyright 2012 Luke Shumaker
+
+This is based on a post on [reddit][1], published on 2012-09-11.
+
+[1]: http://www.reddit.com/r/archlinux/comments/zoffo/systemd_we_will_keep_making_it_the_distro_we_like/c66nrcb
+
+systemd is a replacement for UNIX System V-style init; instead of
+having `/etc/init.d/*` or `/etc/rc.d/*` scripts, systemd runs in the
+background to manage them.
+
+This has the **advantages** that there is proper dependency tracking,
+easing the life of the administrator and allowing for things to be run
+in parallel safely. It also uses "targets" instead of "init levels",
+which just makes more sense. It also means that a target can be
+started or stopped on the fly, such as mounting or unmounting a drive,
+which has in the past only been done at boot up and shut down.
+
+The **downside** is that it is (allegedly) big, bloated[[1](#foot1)], and does
+(arguably) more than it should. Why is there a dedicated systemd-fsck?
+Why does systemd encapsulate the functionality of syslog? That, and it
+means somebody is standing on my lawn.
+
+The **changes** an Arch user needs to worry about is that everything
+is being moved out of `/etc/rc.conf`. Arch users will still have the
+choice between systemd and SysV-init, but rc.conf is becoming the
+SysV-init configuration file, rather than the general system
+configuration file. If you will still be using SysV-init, basically
+the only thing in rc.conf will be `DAEMONS`.[[2](#foot2)] For now
+there is compatibility for the variables that used to be there, but
+that is going away.
+
+[<span id="foot1">1</span>]
+
+*I* don't think it's bloated, but that is the criticism. Basically, I
+discount any argument that uses "bloated" without backing it up. I
+was trying to say that it takes a lot of heat for being bloated, and
+that there is be some truth to that (the systemd-fsck and syslog
+comments), but that these claims are largely unsubstantiated, and more
+along the lines of "I would have done it differently". Maybe your
+ideas are better, but you haven't written the code.
+
+I personally don't have an opinion either way about SysV-init vs
+systemd. I recently migrated my boxes to systemd, but that was because
+the SysV init scripts for NFSv4 in Arch are problematic. I suppose
+this is another **advantage** I missed: *people generally consider
+systemd "units" to be more robust and easier to write than SysV
+"scripts".*
+
+I'm actually not a fan of either. If I had more time on my hands, I'd
+be running a `make`-based init system based on a research project IBM
+did a while ago. So I consider myself fairly objective.
+
+[<span id="foot2">2</span>] You can still have `USEDMRAID`, `USELVM`, `interface`, `address`,
+`netmask`, and `gateway`. But those are minor.
diff --git a/public/assets/style.css b/public/assets/style.css
new file mode 100644
index 0000000..b0ca89c
--- /dev/null
+++ b/public/assets/style.css
@@ -0,0 +1,48 @@
+kbd, code, samp, tt, pre {
+ background: #DDDDDD;
+ white-space: pre;
+}
+
+var {
+ color: #008800;
+}
+
+pre {
+ margin-left: 2em;
+ overflow: auto;
+}
+
+table, td, th {
+ border: solid 1px #AAAAAA;
+}
+
+th {
+ background: #F5F5F5;
+}
+
+table {
+ margin-left: auto;
+ margin-right: auto;
+}
+
+table > caption {
+ text-align: left;
+}
+
+caption > h1 {
+ text-align: center;
+ font-size: 100%;
+}
+
+blockquote {
+ border-left: solid .4em #0000AA;
+ margin-left: .25em;
+ padding-left: 1.25em;
+ font-style: italic;
+}
+
+footer {
+ text-align: center;
+ font-size: 70%;
+ color: #333333;
+}
diff --git a/public/bash-arrays.md b/public/bash-arrays.md
new file mode 100644
index 0000000..697d018
--- /dev/null
+++ b/public/bash-arrays.md
@@ -0,0 +1,201 @@
+Bash arrays
+===========
+:copyright 2013 Luke Shumaker
+
+Way too many people don't understand Bash arrays. Many of them argue
+that if you need arrays, you shouldn't be using Bash. If we reject
+the notion that one should never use Bash for scripting, then thinking
+you don't need Bash arrays is what I like to call "wrong".
+
+The simple expanation of why everybody who programs in Bash needs to
+understand arrays is this: command line arguments are exposed as an
+array. Does your script take any arguments on the command line?
+Great, you need to work with an array!
+
+General array syntax
+--------------------
+
+The most important things to understanding arrays is to quote them,
+and understanding the difference between `@` and `*`.
+
+<table>
+ <caption>
+ <h1>Getting the entire array</h1>
+ <p>There is <em>no</em> valid reason to not wrap these in double
+ quotes.</p>
+ </caption>
+ <tbody>
+ <tr>
+ <td><code>"${array[@]}"</code></td>
+ <td>Returns every element of the array as a separate token.</td>
+ </tr><tr>
+ <td><code>"${array[*]}"</code></td>
+ <td>Returns every element of the array in a single
+ whitepace-separated string.</td>
+ </tr>
+ </tbody>
+</table>
+
+It's really that simple—that covers most usages of arrays, and most of
+the mistakes made with them.
+
+To help you understand the difference between `@` and `*`, here is a
+sample.
+
+<pre><code>#!/bin/bash
+array=(foo bar baz)
+for item in "${array[@]}"; do
+ echo " - &lt;${item}&gt;"
+done<hr> - &lt;foo&gt;
+ - &lt;bar&gt;
+ - &lt;baz&gt;</code></pre>
+
+<pre><code>#!/bin/bash
+array=(foo bar baz)
+for item in "${array[@]}"; do
+ echo " - &lt;${item}&gt;"
+done<hr> - &lt;foo bar baz&gt;</code></pre>
+
+To get individual entries, the syntax is
+<code>${array[<var>n</var>]}</code>, where <var>n</var> starts at 0.
+
+<table>
+ <caption>
+ <h1>Getting a single entry from the array</h1>
+ </caption>
+ <tbody>
+ <tr>
+ <td><code>"${array[<var>n</var>]}"</code></td>
+ <td>Returns the <var>n</var>th entry of the array, where the
+ first entry is at <var>n</var>=0.</td>
+ </tr>
+ </tbody>
+</table>
+
+To get a subset of the array, there are a few options (like normal,
+switch between `@` and `*` to switch between
+getting it as separate items, and as a whitespace-separated string):
+
+<table>
+ <caption>
+ <h1>Getting subsets of an array</h1>
+ <p>Substitute <code>*</code> for <code>@</code> to get the subset
+ as a whitespace-separated string instead of separate tokens, as
+ described above.</p>
+ <p>Again, there is no valid reason to not wrap each of these in
+ double quotes.</p>
+ </caption>
+ <tbody>
+ <tr>
+ <td><code>"${array[@]:<var>start</var>}"</code></td>
+ <td>Returns from <var>n</var>=<var>start</var> to the end of the array.</td>
+ </tr><tr>
+ <td><code>"${array[@]:<var>start</var>:<var>count</var>}"</code></td>
+ <td>Returns <var>count</var> entries, starting at <var>n</var>=<var>start</var>.</td>
+ </tr><tr>
+ <td><code>"${array[@]::<var>count</var>}"</code></td>
+ <td>Returns <var>count</var> entries from the beginning of the array.</td>
+ </tr>
+ </tbody>
+</table>
+
+Notice that `"${array[@]}"` is equivalent to `"${array[@]:0}"`.
+
+<table>
+ <caption>
+ <h1>Getting the length of an array</h1>
+ <p>The is the only situation where there is no difference
+ between <code>@</code> and <code>*</code>.</p>
+ </caption>
+ <tbody>
+ <tr>
+ <td>
+ <code>${#array[@]}</code>
+ <br>or<br>
+ <code>${#array[*]}</code>
+ </td>
+ <td>
+ Returns the length of the array
+ </td>
+ </tr>
+ </tbody>
+</table>
+
+Accessing the arguments array
+-----------------------------
+
+Accessing the arguments is mostly that simple, but that array doesn't
+actually have a variable name. It's special. Instead, it is exposed
+through a series of special variables (normal variables can only start
+with letters and underscore), that *mostly* match up with the normal
+array syntax.
+
+<table>
+ <caption>
+ <h1>Accessing the arguments array</h1>
+ <aside>Note that for values of <var>n</var> with more than 1
+ digit, you need to wrap it in <code>{}</code>.
+ Otherwise, <code>"$10"</code> would be parsed
+ as <code>"${1}0"</code>.</aside>
+ </caption>
+ <tbody>
+ <tr><th colspan=2>Individual entries</th></tr>
+ <tr><td><code>${array[0]}</code></td><td><code>$0</code></td></tr>
+ <tr><td><code>${array[1]}</code></td><td><code>$1</code></td></tr>
+ <tr><td colspan=2 style="text-align:center">...</td></tr>
+ <tr><td><code>${array[9]}</code></td><td><code>$9</code></td></tr>
+ <tr><td><code>${array[10]}</code></td><td><code>${10}</code></td></tr>
+ <tr><td colspan=2 style="text-align:center">...</td></tr>
+ <tr><td><code>${array[<var>n</var>]}</code></td><td><code>${<var>n</var>}</code></td></tr>
+ <tr><th colspan=2>Subset arrays (array)</th></tr>
+ <tr><td><code>"${array[@]}"</code></td><td><code>"${@:0}"</code></td></tr>
+ <tr><td><code>"${array[@]:1}"</code></td><td><code>"$@"</code></td></tr>
+ <tr><td><code>"${array[@]:<var>pos</var>}"</code></td><td><code>"${@:<var>pos</var>}"</code></td></tr>
+ <tr><td><code>"${array[@]:<var>pos</var>:<var>len</var>}"</code></td><td><code>"${@:<var>pos</var>:<var>len</var>}"</code></td></tr>
+ <tr><td><code>"${array[@]::<var>len</var>}"</code></td><td><code>"${@::<var>len</var>}"</code></td></tr>
+ <tr><th colspan=2>Subset arrays (string)</th></tr>
+ <tr><td><code>"${array[*]}"</code></td><td><code>"${*:0}"</code></td></tr>
+ <tr><td><code>"${array[*]:1}"</code></td><td><code>"$*"</code></td></tr>
+ <tr><td><code>"${array[*]:<var>pos</var>}"</code></td><td><code>"${*:<var>pos</var>}"</code></td></tr>
+ <tr><td><code>"${array[*]:<var>pos</var>:<var>len</var>}"</code></td><td><code>"${*:<var>pos</var>:<var>len</var>}"</code></td></tr>
+ <tr><td><code>"${array[*]::<var>len</var>}"</code></td><td><code>"${*::<var>len</var>}"</code></td></tr>
+ <tr><th colspan=2>Array length</th></tr>
+ <tr><td><code>${#array[@]}</code></td><td><code>$#</code> + 1</td></tr>
+ </tbody>
+</table>
+
+Did notice what was inconsistent? The variables `$*`, `$@`, and `$#`
+behave like the <var>n</var>=0 entry doesn't exist.
+
+<table>
+ <caption>
+ <h1>Inconsistencies</h1>
+ </caption>
+ <tbody>
+ <tr>
+ <th colspan=3><code>@</code> or <code>*</code></th>
+ </tr><tr>
+ <td><code>"${array[@]}"</code></td>
+ <td>→</td>
+ <td><code>"${array[@]:0}"</code></td>
+ </tr><tr>
+ <td><code>"${@}"</code></td>
+ <td>→</td>
+ <td><code>"${@:1}"</code></td>
+ </tr><tr>
+ <th colspan=3><code>#</code></th>
+ </tr><tr>
+ <td><code>"${#array[@]}"</code></td>
+ <td>→</td>
+ <td>length</td>
+ </tr><tr>
+ <td><code>"${#}"</code></td>
+ <td>→</td>
+ <td>length-1</td>
+ </tr>
+ </tbody>
+</table>
+
+These make sense because argument 0 is the name of the script—we
+almost never want that when parsing arguments. You'd spend more code
+getting the values that it currently gives you.
diff --git a/public/emacs-as-an-os.md b/public/emacs-as-an-os.md
new file mode 100644
index 0000000..5fe6d4f
--- /dev/null
+++ b/public/emacs-as-an-os.md
@@ -0,0 +1,39 @@
+Emacs as an operating system
+============================
+:copyright 2013 Luke Shumaker
+
+This was originally published on [Hacker News][1] on 2013-08-29.
+
+[1]: https://news.ycombinator.com/item?id=6292742
+
+Calling Emacs an OS is dubious, it certainly isn't a general purpose
+OS, and won't run on real hardware. But, let me make the case that
+Emacs is an OS.
+
+Emacs has two parts, the C part, and the Emacs Lisp part.
+
+The C part isn't just a Lisp interpreter, it is a Lisp Machine
+emulator. It doesn't particularly resemble any of the real Lisp
+machines. The TCP, Keyboard/Mouse, display support, and filesystem are
+done at the hardware level (the operations to work with these things
+are among the primitive operations provided by the hardware). Of
+these, the display being handled by the hardware isn't particularly
+uncommon, historically; the filesystem is a little stranger.
+
+The Lisp part of Emacs is the operating system that runs on that
+emulated hardware. It's not a particularly powerful OS, it not a
+multi-tasking system. It has many packages available for it (though
+not until recently was there a official package manager). It has
+reasonably powerful IPC mechanisms. It has shells, mail clients (MUAs
+and MSAs), web browsers, web servers and more, all written entirely in
+Emacs Lisp.
+
+My might say "but a lot of that is being done by the host operating
+system!" Sure, some of it is, but all of it is sufficiently low
+level. If you wanted to share the filesystem with another OS running
+in a VM, you might do it by sharing it as a network filesystem; this
+is necessary when the VM OS is not designed around running in a
+VM. However, because Emacs OS will always be running in the Emacs VM,
+we can optimize it by having the Emacs VM include processor features
+mapping the native OS, and have the Emacs OS be aware of them. It
+would be slower and more code to do that all over the network.
diff --git a/public/emacs-shells.md b/public/emacs-shells.md
new file mode 100644
index 0000000..fdd5bcb
--- /dev/null
+++ b/public/emacs-shells.md
@@ -0,0 +1,63 @@
+A summary of Emacs' bundled shell and terminal modes
+====================================================
+:copyright 2013 Luke Shumaker
+
+This is based on a post on [reddit][1], published on 2013-04-09.
+
+[1]: http://www.reddit.com/r/emacs/comments/1bzl8b/how_can_i_get_a_dumbersimpler_shell_in_emacs/c9blzyb
+
+Emacs comes bundled with a few different shell and terminal modes. It
+can be hard to keep them straight. What's the difference between
+`M-x term` and `M-x ansi-term`?
+
+Here's a good breakdown of the different bundled shells and terminals
+for Emacs, from dumbest to most Emacs-y
+
+**term-mode**: Your VT100-esque terminal emulator; it does what most
+terminal programs do. Ncurses-things work OK, but dumping large
+amounts of text can be slow. By default it asks you which shell to
+run, defaulting to the environmental variable `$SHELL` (`/bin/bash` for
+me). There are two modes of operation:
+
+* char mode: Keys are sent immediately to the shell (including keys
+ that are normally Emacs keystrokes), with the following exceptions:
+ * `(term-escape-char) (term-escape-char)` sends `(term-escape-char)`
+ to the shell (see above for what the default value is).
+ * `(term-escape-char) <anything-else>` is like doing equates to `C-x
+ <anything-else>` in normal Emacs.
+ * `(term-escape-char) C-j` switches to line mode.
+* line mode: Editing is done like in a normal Emacs buffer, `<enter>`
+ sends the current line to the shell. This is useful for working with
+ a program's output.
+ * `C-c C-k` switches to char mode.
+
+This mode is activated with
+
+ ; Creates or switches to an existing "*terminal*" buffer.
+ ; The default 'term-escape-char' is "C-c"
+ M-x term
+
+or
+
+ ; Creates a new "*ansi-term*" or "*ansi-term*<n>" buffer.
+ ; The default 'term-escape-char' is "C-c" and "C-f"
+ M-x ansi-term
+
+**shell-mode**: The name is a misnomer; shell-mode is a terminal
+emulator, not a shell; it's called that because it is used for running
+a shell (bash/zsh...). The idea of this mode is to use an external
+shell, but make it Emacs-y. History is not handled by the shell, but
+by Emacs; `M-p` and `M-n` access the history, while arrows/`C-p`/`C-n`
+move the point (which is is consistent with other Emacs REPL-type
+interfaces). It ignores VT100-type terminal colors, and colorizes
+things itself (it inspects words to see if they are directories, in
+the case of `ls`). This has the benefit that it does syntax
+highlighting on the currently being typed command. Ncurses programs
+will of course not work. This mode is activated with:
+
+ M-x shell
+
+**eshell-mode**: This is a shell+terminal, entirely written in Emacs
+lisp. (Interestingly, it doesn't set `$SHELL`, so that will be whatever
+it was when you launched Emacs). This won't even be running zsh or
+bash, it will be running "esh", part of Emacs.
diff --git a/public/fd_printf.md b/public/fd_printf.md
new file mode 100644
index 0000000..5e1098e
--- /dev/null
+++ b/public/fd_printf.md
@@ -0,0 +1,37 @@
+`fd_printf`: print formatted text directly to a file descriptor
+===============================================================
+:copyright 2013 Luke Shumaker
+:license WTFPL-2
+
+I wrote this while debugging some code, and thought it might be useful
+to others:
+
+ #define _GNU_SOURCE /* vasprintf() */
+ #include <stdarg.h> /* va_start()/va_end() */
+ #include <stdio.h> /* vasprintf() */
+ #include <stdlib.h> /* free() */
+ #include <unistd.h> /* write() */
+
+ int
+ fd_printf(int fd, const char *format, ...)
+ {
+ va_list arg;
+ int len;
+ char *str;
+
+ va_start(arg, format);
+ len = vasprintf(&str, format, arg);
+ va_end(arg);
+
+ write(fd, str, len);
+
+ free(str);
+ return len;
+ }
+
+
+It is a version of `printf` that prints to a file descriptor—where
+`fprintf` prints to a `FILE*` data structure.
+
+The appeal of this is that `FILE*` I/O is buffered—which means mixing
+it with raw file descriptor I/O is going to produce weird results.
diff --git a/public/fs-licensing-explanation.md b/public/fs-licensing-explanation.md
new file mode 100644
index 0000000..ad170a3
--- /dev/null
+++ b/public/fs-licensing-explanation.md
@@ -0,0 +1,62 @@
+An explanation of how "copyleft" licensing works
+================================================
+:copyright 2013 Luke Shumaker
+
+This is based on a post on [reddit][1], published on 2013-02-21.
+
+[1]: http://www.reddit.com/r/freesoftware/comments/18xplw/can_software_be_free_gnu_and_still_be_owned_by_an/c8ixwq2
+
+> While reading the man page for readline I noticed the copyright
+> section said "Readline is Copyright (C) 1989-2011 Free Software
+> Foundation Inc". How can software be both licensed under GNU and
+> copyrighted to a single group? It was my understanding that once
+> code became free it didn't belong to any particular group or
+> individual.
+>
+> [LiveCode is GPLv3, but also sells non-free licenses] Can you really
+> have the same code under two conflicting licences? Once licensed
+> under GPL3 wouldn't they too be required to adhere to its rules?
+
+I believe that GNU/the FSF has an FAQ that addresses this, but I can't
+find it, so here we go.
+
+### Glossary:
+
+ * "*Copyright*" is the right to control how copies are made of
+ something.
+ * Something for which no one holds the copyright is in the "*public
+ domain*", because anyone ("the public") is allowed to do *anything*
+ with it.
+ * A "*license*" is basically a legal document that says "I promise
+ not to sue you if make copies in these specific ways."
+ * A "*non-free*" license basically says "There are no conditions
+ under which you can make copies that I won't sue you."
+ * A "*permissive*" (type of free) license basically says "You can do
+ whatever you want, BUT have to give me credit", and is very similar
+ to the public domain. If the copyright holder didn't have the
+ copyright, they couldn't sue you to make sure that you gave them
+ credit, and nobody would have to give them credit.
+ * A "*copyleft*" (type of free) license basically says, "You can do
+ whatever you want, BUT anyone who gets a copy from you has to be
+ able to do whatever they want too." If the copyright holder didn't
+ have the copyright, they couldn't sue you to make sure that you
+ gave the source to people go got it from you, and non-free versions
+ of these programs would start to exist.
+
+### Specific questions:
+
+Readline: The GNU GPL is a copyleft license. If you make a modified
+version of Readline, and don't let others have the source code, the
+FSF will sue you. They can do this because they have the copyright on
+Readline, and in the GNU GPL (the license they used) it only says that
+they won't sue you if you distribute the source with the modified
+version. If they didn't have the copyright, they couldn't sue you,
+and the GNU GPL would be worthless.
+
+LiveCode: The copyright holder for something is not required to obey
+the license—the license is only a promise not to sue you; of course
+they won't sue themselves. They can also offer different terms to
+different people. They can tell most people "I won't sue you as long
+as you share the source," but if someone gave them a little money,
+they might say, "I also promise not sue sue this guy, even if he
+doesn't give out the source."
diff --git a/public/git-go-pre-commit.md b/public/git-go-pre-commit.md
new file mode 100644
index 0000000..74dca28
--- /dev/null
+++ b/public/git-go-pre-commit.md
@@ -0,0 +1,54 @@
+A git pre-commit hook for automatically formatting Go code
+==========================================================
+:copyright 2013 Luke Shumaker
+:license WTFPL-2
+
+One of the (many) wonderful things about the Go programming language
+is the `gofmt` tool, which formats your source in a canonical way. I
+thought it would be nice to integrate this in my `git` workflow by
+adding it in a pre-commit hook to automatically format my source code
+when I commited it.
+
+The Go distribution contains a git pre-commit hook that checks whether
+the source code is formatted, and aborts the commit if it isn't. I
+don't remember if I was aware of this at the time (or if it even
+existed at the time, or if it is new), but I wanted it to go ahead and
+format the code for me.
+
+I found a few solutions online, but they wre all missing
+something—support for partial commits. I frequently use `git add
+-p`/`git gui` to commit a subset of the changes I've made to a file,
+the existing solutions would end up adding the entire set of changes
+to my commit.
+
+I ended up writing a solution that only formats the version of the
+that is staged for commit; here's my `.git/hooks/pre-commit`:
+
+ #!/bin/bash
+
+ # This would only loop over files that are already staged for commit.
+ # git diff --cached --numstat |
+ # while read add del file; do
+ # ...
+ # done
+
+ shopt -s globstar
+ for file in **/*.go; do
+ tmp="$(mktemp "$file.bak.XXXXXXXXXX")"
+ mv "$file" "$tmp"
+ git checkout "$file"
+ gofmt -w "$file"
+ git add "$file"
+ mv "$tmp" "$file"
+ done
+
+It's still not perfect. It will try to operate on every `*.go`
+file—which might do weird things if you have a file that hasn't been
+checked in at all. This also has the effect of formatting files that
+were checked in without being formatted, but weren't modified in this
+commit.
+
+I don't remember why I did that—as you can see from the comment, I
+knew how to only select files that were staged for commit. I haven't
+worked on any projects in Go in a while—if I return to one of them,
+and remember why I did that, I will update this page.
diff --git a/public/pacman-overview.md b/public/pacman-overview.md
new file mode 100644
index 0000000..579adba
--- /dev/null
+++ b/public/pacman-overview.md
@@ -0,0 +1,48 @@
+A quick overview of usage of the Pacaman package manager
+========================================================
+:copyright 2013 Luke Shumaker
+
+This was originally published on [Hacker News][1] on 2013-01-23.
+
+[1]: https://news.ycombinator.com/item?id=5101416
+
+Note: I've over-done quotation marks to make it clear when precise
+wording matters.
+
+`pacman` is a little awkward, but I prefer it to apt/dpkg, which have
+sub-commands, each with their own flags, some of which are
+undocumented. pacman, on the other hand, has ALL options documented in
+one fairly short man page.
+
+The trick to understanding pacman is to understand how it maintains
+databases of packages, and what it means to "sync".
+
+There are several "databases" that pacman deals with:
+
+ * "the database", (`/var/lib/pacman/local/`)<br>
+ The database of currently installed packages
+ * "package databases", (`/var/lib/pacman/sync/${repo}.db`)<br>
+ There is one of these for each repository. It is a file
+ that is fetched over plain http(s) from the server; it
+ is not modified locally, only updated.
+
+The "operation" of pacman is set with a capital flag, one of "DQRSTU"
+(plus `-V` and `-h` for version and help). Of these, "DTU" are "low-level"
+(analogous to dpkg) and "QRS" are "high-level" (analogous to apt).
+
+To give a brief explanation of cover the "high-level" operations, and
+which databases they deal with:
+
+ * "Q" Queries "the database" of locally installed packages.
+
+ * "S" deals with "package databases", and Syncing "the database" with
+ them; meaning it installs/updates packages that are in package
+ databases, but not installed on the local system.
+
+ * "R" Removes packages "the database"; removing them from the local
+ system.
+
+The biggest "gotcha" is that "S" deals with all operations with
+"package databases", not just syncing "the database" with them.
+
+
diff --git a/public/poor-system-documentation.md b/public/poor-system-documentation.md
new file mode 100644
index 0000000..0c97e40
--- /dev/null
+++ b/public/poor-system-documentation.md
@@ -0,0 +1,38 @@
+Why documentation on GNU/Linux sucks
+====================================
+:copyright 2012 Luke Shumaker
+
+This is based on a post on [reddit][1], published on 2012-09-12.
+
+[1]: http://www.reddit.com/r/archlinux/comments/zoffo/systemd_we_will_keep_making_it_the_distro_we_like/c66uu57
+
+The documentation situation on GNU/Linux based operating systems is
+right now a mess. In the world of documentation, there are basically 3
+camps, the "UNIX" camp, the "GNU" camp, and the "GNU/Linux" camp.
+
+The UNIX camp is the `man` page camp, they have quality, terse but
+informative man pages, on *everything*, including the system's design
+and all system files. If it was up to the UNIX camp, `man grub.cfg`,
+`man grub.d`, and `man grub-mkconfig_lib` would exist and actually be
+helpful. The man page would either include inline examples, or point
+you to a directory. If I were to print off all of the man pages, it
+would actually be a useful manual for the system.
+
+Then GNU camp is the `info` camp. They basically thought that each
+piece of software was more complex than a man page could handle. They
+essentially think that some individual pieces software warrant a
+book. So, they developed the `info` system. The info pages are usually
+quite high quality, but are very long, and a pain if you just want a
+quick look. The `info` system can generate good HTML (and PDF, etc.)
+documentation. But the standard `info` is awkward as hell to use for
+non-Emacs users.
+
+Then we have the "GNU/Linux" camp, they use GNU software, but want to
+use `man` pages. This means that we get low-quality man pages for GNU
+software, and then we don't have a good baseline for documentation,
+developers each try to create their own. The documentation that gets
+written is frequently either low-quality, or non-standard. A lot of
+man pages are auto-generated from `--help` output or info pages,
+meaning they are either not helpful, or overly verbose with low
+information density. This camp gets the worst of both worlds, and a
+few problems of its own.
diff --git a/public/term-colors.md b/public/term-colors.md
new file mode 100644
index 0000000..bb945d0
--- /dev/null
+++ b/public/term-colors.md
@@ -0,0 +1,40 @@
+An explanation of common terminal emulator color codes
+======================================================
+:copyright 2013 Luke Shumaker
+
+This is based on a post on [reddit][1], published on 2013-03-21.
+
+[1]: http://www.reddit.com/r/commandline/comments/1aotaj/solarized_is_a_sixteen_color_palette_designed_for/c8ztxpt?context=1
+
+> So all terminals support the same 256 colors? What about 88 color
+> mode: is that a subset?
+
+TL;DR: yes
+
+Terminal compatibility is crazy complex, because nobody actually reads
+the spec, they just write something that is compatible for their
+tests. Then things have to be compatible with that terminal's quirks.
+
+But, here's how 8-color, 16-color, and 256 color work. IIRC, 88 color
+is a subset of the 256 color scheme, but I'm not sure.
+
+**8 colors: (actually 9)**
+First we had 8 colors (9 with "default", which doesn't have to be one
+of the 8). These are always roughly the same color: black, red, green,
+yellow/orange, blue, purple, cyan, and white, which are colors 0-7
+respectively. Color 9 is default.
+
+**16 colors: (actually 18)**
+Later, someone wanted to add more colors, so they added a "bright"
+attribute. So when bright is on, you get "bright red" instead of
+"red". Hence 8*2=16 (plus two more for "default" and "bright
+default").
+
+**256 colors: (actually 274)**
+You may have noticed, colors 0-7 and 9 are used, but 8 isn't. So,
+someone decided that color 8 should put the terminal into 256 color
+mode. In this mode, it reads another byte, which is an 8-bit RGB value
+(2 bits for red, 2 for green, 2 for blue). The bright property has no
+effect on these colors. However, a terminal can display 256-color-mode
+colors and 16-color-mode colors at the same time, so you actually get
+256+18 colors.
diff --git a/template.erb b/template.erb
new file mode 100644
index 0000000..01ad125
--- /dev/null
+++ b/template.erb
@@ -0,0 +1,20 @@
+<!DOCTYPE html>
+<html lang="en">
+<head>
+ <meta charset="utf-8">
+ <title><%= @title %></title>
+ <link rel="stylesheet" type="text/css" href="assets/style.css">
+</head>
+<body>
+<header>
+<a href="./">Luke Shumaker's ramblings</a>
+</header>
+<article>
+<%= @content %>
+</article>
+<footer>
+<p>The content of this page is Copyright © <%= @copyright %>.</p>
+<p>This page is licensed under the <%= @license %> license.</p>
+</footer>
+</body>
+</html>