Wednesday, March 28, 2018

A Comprehensive Review of Alex Garland's Film Annihilation, Compendious in Its Correctness (Also It Is: Indisputable)

Point 1.

Oh, Alex Garland.

Point 2.

Here are some things that are extremely cool.

  • that one episode of X-Files where the scientists in the Arctic discover a creepy worm alien or whatever and the one guy yells "We're not ... who we ARE!"
  • The Thing
  • 2001
  • Alien / Aliens
  • Heart of Darkness / Apocalypse Now / going up a river to where humanity disintegrates

Tuesday, March 27, 2018

Vim (for non-programmers) Part Three: Refactoring my .vimrc File, Chapter Five; Correct Easy Markup of Markdown Headlines (Building on Chris Toomey's "Your First Vim Plugin")

At some point in the quest to have The World's Greatest .vimrc File, a person will naturally begin to explore the wider surround, see what the community is up to on the weird-ass-solutions-to-incredibly-narrow-problems front. Since, sometimes, work, life, and other responsibilities exert their gravitationals* upon a person, one helpful way to perform this exploration is to throw on a YouTube video in the background while waiting for the requiring hordes to get bored waiting for me to do the needful and go bother somebody else. I.e., it can be kind of fun to half-listen to somebody, and sometimes you get interesting hints while you're ostensibly, or even actually, working on something else...

*Read: suck.

A great place to start is with Chris Toomey's "Your First Vim Plugin" talk.

Toomey comes across like a delightful fellow, smart and approachable, and his basic approach to creating a plugin seems exactly right to me:

  • Find a problem (something that's difficult, or time-consuming, or repetitive to do)
  • Figure out a working solution (that is easier, or faster, or that eliminates repetition)
  • Drop it in your .vimrc
  • Tinker with it as you find that it needs improvement
  • Eventually abstract it and pull it out of your .vimrc, if you feel like it or if you feel like sharing it

Since I tend to take a lot of my notes in Markdown**, his Markdown underlining approach really made sense to me: a quick and dirty mapping to make something an H1 headline or H2 headline fits my workflow nicely—particularly after abstracting it a tiny bit so that one mapping, <leader>h1, adds the appropriate headlining markup whether I'm writing HTML or Markdown (which Vim knows because it's smart about filetypes!).

**What's Markdown? For most people, it's a way to write very lightly formatted text that can be submitted to another program, and out is spit nicely formatted HTML or something that looks pretty pasted into a Word doc or something. For me, it's a way to tell Vim "Please treat a raw .txt file like it's something else, including pretty syntax highlighting that makes it easier to see what's what." It looks like so:

Here's Chris Toomey's approach:

:nnoremap <leader>h1 :normal! "yypVr=<esc>"
:nnoremap
– in normal mode, ignoring all other mappings
<leader>h1 – when I type the leader key, then h then 1, act like I typed the next line (without quotes)
:normal! "yypVr=<esc>"
yypVr=yy means "yank (copy) the entire line";
p means "put (paste), in this case, the entire line"
V means "visually select (highlight) the entire line"
r= uses the r command followed by another character to mean "replace the character under the cursor with the character typed after r"; in this case, since the entire line has been visually selected, in effect, every character in the line is under the cursor, so every character in the line gets replaced with an equals sign character, which is the Markdown character that makes a headline

It works, it's lightning-fast, and it's completely transparent! I dumped it into my .vimrc immediately, and changed two characters so it would also work for h2 tags (by adding a line of hyphens, not equals signs):

:nnoremap <leader>h2 :normal! "yypVr-<esc>"

This overall approach, in which you come up with a solution that can then be extended, is super congenial to me, and I'm beyond stoked that Toomey put it in front of me. After a while, though, the specific nature of the solution started to bug me a little bit.

The problem was that, at an abstract level, I didn't want to:

Copy a line
Paste a copy of the line beneath the first line
Replace all the characters in the second line with a Markdown markup character

What I wanted to do was:

Given a certain line
Create a line underneath it
With as many markdown markup characters as the given line had characters (including tabs or whatever) so it looks pretty

So I set about trying to make something that would do those things.

Oddly, I succeeded. Here's how it went down.

Vim's built-in programming language, VimScript, has a big library of built-in functions, some of which interact with text. You can check them out at :help functions and :help function-list. After poking around in them and fiddling around getting frustrated for a while, I was able to write the following one-liner, which did exactly what I wanted:

:call append(".", repeat("=", strdisplaywidth(getline("."))))

Let's read that from the inside out:

getline(".") is a function that fetches a line in the current buffer (read buffer for our purposes as "the file we're working on"); what goes in the parentheses is the line number, and "." is the wildcard that means "the line the cursor is on"
strdisplaywidth() is a function that looks at a string and tells you how wide it is, in characters displayed on the screen – including tabs and what have you. The trick with this function is that it can take as its argument another function; put the two functions together as we have, and it means "get the line under the cursor, then tell me how long it is"
repeat("=", 68) is trickier: the way the help describes it as a generic function is repeat({expression}, {count}), which means "do the {expression}, which is the thing inside quotes and before the comma, a number of times specified in {count}". Here I've told it that the expression is the equals sign, which is the character we use in Markdown to underline something that's a headline, and I've yet again fed it, instead of a number, the result of a function, our earlier "get the line under the cursor, then tell me how long it is"
append(".", {text}) is a bit of an easier one by now. append()'s arguments say "after a specified line, insert {text}". Here, we re-use the "." wildcard to specify that the line we want to start with is the line under the cursor, and the text we want to be inserted is the result of the repeat("=", strdisplaywidth(getline(".))) series of functions. Simple!

I can do this any time just by putting the cursor on the line I want and typing:
:call append(".", repeat("=", strdisplaywidth(getline("."))))

That's a lot of relatively persnickety typing to have to do, though. The approach I took was what I take to be a relatively common one, but one that I may very well be misunderstanding! What I did was:

  1. Wrapped the 'sucker in a (script-specific) function of my own
  2. Defined a special command to call the function
  3. Made a mapping that will call that command when I'm writing Markdown, but will call a different command when I'm writing something else

What I may be misunderstanding is why exactly I needed my own function. It seems to simplify using the same mapping to call a variety of different commands, but it may be an unneeded step. Anyway, as it lives in my .vimrc file, it looks like the following:

function! s:MarkdownHeadline1()
:call append(".", repeat("=", strdisplaywidth(getline("."))))
endfunction
command! MarkdownHeadline1 call s:MarkdownHeadline1()

function! s:MarkdownHeadline2()
:call append(".", repeat("-", strdisplaywidth(getline("."))))
endfunction
command! MarkdownHeadline2 call s:MarkdownHeadline2()


function! s:MakeHeadlines()
if &filetype == 'markdown'
echo "Markdown!"
" :nnoremap h1 yypVr=
:nnoremap h1 :MarkdownHeadline1
" :nnoremap h2 yypVr-
:nnoremap h2 :MarkdownHeadline2
:nnoremap li I-
" other stuff elided for clarity
endif
endfunction
command! MakeHeadlines call s:MakeHeadlines()

The MakeHeadlines() function is growing, slowly, and as I get it to do more stuff that I want it to do, it's slowly outgrowing its little name. By the time I'll abstract it into something more broadly useful and extract it into a real plugin, not just a chunk of code sitting in my .vimrc file, I will rename it "Corduroy."

Previous entries in Vim (for non-programmers):

Image yoinked from: http://zedisred.blogspot.com/2011/05/let-me-win-your-heart-and-mind-or-ill.html.

Thursday, March 15, 2018

your battle is also ours

Doctor Strange Master of the Mystic Arts, Jim Starlin art



...when my merest touch

Doctor Strange Master of the Mystic Arts, Gene Colan art




Wednesday, March 14, 2018

Vim (for non-programmers) Part Three: Refactoring my _vimrc File; Chapter Five: Correct Easy Link Addition (Correcting My Misreading of Steve Losh)

As we've seen in previous entries, I've decided to refactor my somewhat creaky, bloated _vimrc file. (For one thing, it was more or less organized chronologically, which makes a certain kind of sense—it certainly reflects an increasing sophistication (or anyway complexity) to my efforts—but also is obviously an insane way to organize configuration settings for anything. For another, I have a tendency to want to hold on to everything I ever tried, so I have, for example, an entire section called "Experiments That Failed Too Many Times".)

Part of the refactoring process, though, involves more than just reordering elements in the file: it involves examining those elements and determining if they could stand some improving.

One of the most vital resources for customizing your _vimrc is Steve Losh's Learn Vimscript the Hard Way. While I was working my way through (the early parts of) this book, I fell in love with a mapping he suggested for surrounding a word with double quotes. (As we know, mappings are a way to tell Vim, "When I type X, please act as though I typed Y". To keep from typing X accidentally, it's common to use a "leader" key followed by a short mnemonic. Because Vim is incredibly complicated, you have to specify what mode the mapping operates in, and you have to specify whether or not the mapping is recursive. This means a mapping is almost impossible to parse visually, because it has the form:
MODE_MAPPING_IS_FOR I_TYPE_THIS YOU_ACT_AS_THOUGH_I_TYPED_THIS
Which, given Vim's predilection for being hella terse, and the obvious utility to tell it "When I type something very short and easy to type, act as though I typed something very long and difficult to type", makes reading mappings difficult.)

viw<ESC>a"<ESC>bi"<ESC>lel
viw
– visually select the current word (the word the cursor is on)
<ESC> – exit visual mode / return to normal mode
a – enter insert mode after the character the cursor is on
" – insert a double quote <ESC> – exit insert mode / return to normal mode
b – move to beginning of word the cursor is on
i – enter insert mode before the character the cursor is on
" – insert a double quote
<ESC> – exit insert mode / return to normal mode
l – move cursor right one character (back onto the word)
e – move to end of word
l – move cursor right one character (onto the closing double quote)

As an exercise, he suggested a more advanced mapping that added double quotes around the last thing that had been visually suggested. I was quite taken with this approach, and, reasoning that HTML tags came in pairs just like quotation marks, I adapted his mappings so that I could quickly add hyperlinks to the word the cursor was on, or to the last thing I had visually suggested. The chunk of my _vimrc containing these mappings read like so (please be impressed with my incredible commitment to code documentation via comment):

" make the word under the cursor a hyperlink to URL from system clipboard
" 18jan2016
" mapping <leader>a to:
" select the current word with viw
" wrap the current word in an <a href> tag
" by moving to the end of the word and adding </a> to close the tag
" then moving to the beginning of the WORD and adding <a href="">
" moving back to the beginning of the WORD to move to the quotes
" and populate the quotes with the contents of the + register
" mostly inspired by Steve Losh
" edited 27dec2016
" :nnoremap <leader>a viw<esc>a</a><esc>Bi<a href=""><esc>Bci"<esc>a<c-r>+<esc>
:nnoremap <leader>a viw<esc>a</a><esc>Bi<a href="<c-r>+<esc>a"><esc>


" make the last visually selected text a hyperlink to URL from system clipboard
" 18jan2016
" mapping <leader>v to:
" select the last visual selection with `< and `>
" wrap that selection in an <a href> tag
" by moving to the end of the visual selection and adding </a> to close the tag
" then moving to the beginning of the visual selection and adding <a href="">
" moving back to the beginning of the visual selection to move to the quotes
" and populate the quotes with the contents of the + register
" mostly inspired by Steve Losh
:nnoremap <leader>v `><esc>a</a><esc>`<i<a href=""><esc>Bci"<esc>a<c-r>+<esc>

This allowed me to use two keystrokes—<leader>v or <leader>a—to add links to my text. This is an extremely handy shortcut—especially when working here in Reviewiera, where it's often the case that to make the case that some stuff is better than some other stuff, it is helpful to link to stuff, and then again to other stuff.

The one big problem I had with this mapping is that it didn't work if the line had quotes in it, because my clever ci" motion "selects the text from the previous quote until the next quote" (see :help a"). This meant that when I wanted to add my links to, say, a paragraph where I had mentioned the title of something, I had to:

  1. Enter some line breaks before and after the text I wanted to add links to
  2. Then add the links
  3. Then remove the line breaks

This pretty severely compromised the whole point of having a quick-keystroke method for adding links. And because I didn't look up the behavior of ci" until I was typing this up, I wasn't entirely certain what the glitch was! All I knew was that I had had to create a workaround when the line before whatever I wanted to add a link to included double quotes.

Today, in a meeting, I decided this was no longer an acceptable way to go about my business, so I put the matter to some thought, and decided:

  • Steve Losh was wrong and his approach to selecting a word then moving the cursor around manually wasn't the best
  • The way to craft this mapping properly would leverage Vim's multiple registers (registers are basically clipboards with names: the ones you can assign are a, b, c ... z, and this was something I abused a lot in my early days using Vim)

I sketched it out on paper before trying anything on the laptop, and, oddly, it turned out to work pretty much exactly as designed. Here's what it looks like:

:nnoremap <leader>a "zdiwi<a href="<CTRL-r>+"<CTRL-z</a><ESC>

As I was working on it and testing it, I realized that the problem wasn't Steve Losh at all, the problem was all me! But now I have a couple extremely sexy mappings that work when I personally need them to work. Just for grins, let's break them down and see what they do.

:nnoremap <leader>a "zdiwi<a href="<CTRL-r>+"<CTRL-z</a><ESC> "z – into the z buffer ... diw – delete the word the cursor is on (not including any surrounding whitespace) i – enter insert mode <a href=" – type <a href=" <CTRL-r> – hold down Control and r at the same time (in insert mode, this allows pasting from registers) + – the + register is the system clipboard, where we assume the URL is <CTRL-r> – hold down Control and r at the same time (in insert mode, this allows pasting from registers) z – paste the z register in (this is the word we deleted at first) </a> – close the html tag <ESC> – exit insert mode / return to normal mode

What I like about this is that it works left-to-right, in a more or less sensible way. It basically does exactly what I would do if I were typing: the bulk of the mapping is just banging away in insert mode; typing in the <a href=", then using <CTRL-r>+ to drop in the URL from the clipboard is precisely how I tended to add links before I started fiddling around with mappings in the first place. Also, since I rarely use named registers, I think it's okay to have this mapping clobber the z register. However, as a best practice slash approximation to idiomatically written Vimscript, I think the following mapping is probably better:

:nnoremap <leader>a diwi<a href="<c-r>+"><c-r>"</a><esc>

This just deletes the word, which by default places it into the unnamed register (see :help quotequote), which can be accessed by calling it by the name '"'. (By this point in the series, we should be far beyond being surprised or upset by trivialities like the fact that you can name an unnamed register...)

The visual mapping is a little bit trickier, but only a little bit. It uses exactly the same left-to-right approach, but leverages a fancy little command: gv, which in normal mode re-selects the last visual selection. NOTE: the g prefix in normal mode does some seriously under-known shit. In February of 2015, Tim Chase, one of the heroes on the Vim list, dropped this little gem:

Also, just in case you need it, "g&" is an obscure "across all lines in the file, repeat the last substitution with the same flags" command, even if it's several items back in your command-line history.

Like, seriously, what the hell, Vim? That's a LOT of power to pack into two keystrokes. Anyway, let's check out visual-mode link-adding.

:nnoremap <leader>v gvdi<a href="<c-r>+"><c-r>"</a><esc>
gv – re-select the last visual selection
d – delete what's selected
i – enter insert mode
<a href=" – type <a href="
<CTRL-r> – hold down Control and r at the same time (in insert mode, this allows pasting from registers)
+ – the + register is the system clipboard, where we assume the URL is
<CTRL-r> – hold down Control and r at the same time (in insert mode, this allows pasting from registers)
" – paste the so-called unnamed register in (this is the word we deleted at first)
</a> – close the html tag
<ESC> – exit insert mode / return to normal mode

Again, this is a simpler approach than Losh's, which goes right-to-left, then has to jump back to the right when it's done. Literally everything else he says and does makes a hell of a lot more sense than anything else I say or do, of course.

Anyway, that's two mappings refactored! I only have the entire rest of my _vimrc to go.