using tmux with vim: a screencast
02 Jul 2014I made another screencast. I think in retrospect I should have recorded the screencast part first and then later added commentary.
Learning!
I made another screencast. I think in retrospect I should have recorded the screencast part first and then later added commentary.
Learning!
This is the first post in the series. The second post is available here.
There's been a refreshing wave of change in the way we build web applications in PHP over the last few years. The advent of Composer and the wave of modular, reusable components it's brought us have dramatically improved the architecture of new applications. Unfortunately for the developers forced to maintain them, not all applications are taking advantage of these new and powerful tools. In this series I'll be discussing the process of upgrading and refactoring a typical "old school" site built with PHP into a solid, well tested application.
Let's first discuss what we're working with. I'm assuming a multipage site with
multiple entry points. The ones I've seen and worked with tend to have lines
like include "inc/header.php"
. There's frequently code that's been copied and
pasted in multiple places, and these snippets often have minute and unmarked
differences. There's rarely any form of testing or build process, and the
business login is often intertwined with the display login.
Note: this process is not specific to PHP or even to sites structured like this, but for simplicity's sake (and because of how often I see sites like this in the wild) this is the base we'll be working from.
Now that we know what we're working with, let's establish what we'd like to end up with:
A single entry point (index.php
) in the public web directory
A full set of tests, both unit and functional, that insure the site is functioning correctly at all times
A modern deployment process, using Docker, Nginx, and PHP-FPM
A way of interacting with the code from the command line effectively. Any HTTP request should be able to be perfectly simulated from any SAPI (cli, phpdbg, etc.)
Let's begin.
I was recently asked to write a small C script for reading some basic system stats. Nothing particularly exciting, and certainly not worth including any large unit testing frameworks for. Going without any tests at all (going commando) just doesn't feel right though. Instead, I decided to use Perl and its Test::Simple module to write some quick tests.
Here's our program (stored in script.c
, compiled to script
):
#include <stdio.h>
int main(int argc, const char* argv[]) {
printf("argc: %d", argc);
if (argc == 1) {
printf("you called this script with no arguments\n");
} else if (argc == 2) {
printf("you called this script with 1 argument\n");
} else {
printf("you called this script with %d arguments\n", argc - 1);
}
return 0;
}
Easy enough, we can test this. Here's our test script:
#!/usr/bin/env perl -w
use strict;
use warnings;
use Test::Simple tests => 4;
ok(`./script` =~ /no arguments$/, "no args");
ok(`./script foo` =~ /1 argument$/, "1 arg");
ok(`./script foo bar` =~ /2 arguments$/, "2 args");
ok(`./script foo bar baz` =~ /3 arguments$/, "3 args");
Super simple. Let's go over the parts of the script.
#!/usr/bin/env perl -w
Perl's she-bang line. This just tells the kernel to run this script using the
user's Perl bin with the -w
(warn) flag on. Normally Perl let's you get away
with a lot of nonsense, and the -w
flag restricts the level of nonsense that's
acceptable.
Note: this post originally stated that the she-bang line was for the shell. It's actually for the kernel. The More You Know™
use Test::Simple tests => 4;
Use the Test::Simple
pod. The most important part here is the tests => 4
,
which is where we tell the script that we're planning to run 4 tests. That way
it knows that if a different number of tests are run something went wrong and
it'll tell us.
ok(`./script` =~ /no arguments$/, "no args")
ok(`./script foo` =~ /1 argument$/, "1 arg")
ok(`./script foo bar` =~ /2 arguments$/, "2 args")
ok(`./script foo bar baz` =~ /3 arguments$/, "3 args")
Ah, the meat of the script. The ok
subroutine just tallies up a passed test if
the first argument is true or a failed test if it evaluates to false. The second
(optional) argument is a test title.
The backticks (`
) around the ./script
execute the command and return
the stdout. The =~
just returns true if the regex on the right matches
the string on the left.
Running the script gets us:
λ ./test.pl
1..4
ok 1 - no args
ok 2 - 1 arg
ok 3 - 2 args
ok 4 - 3 args
There, that's an easy (and lightweight) way of testing simple cli scripts.
Vim is my editor of choice. I was recently playing around with a Fedora
installation and realized that even the vim-enhanced
package available via
yum
was not as feature-complete as the one on my MacBook (compiled with
homebrew's help).
I decided I'd need to compile it from scratch. Here's how I did that:
Note: I already had multiple versions of Ruby compiled from a previous Ansible script I ran. You may have to get Ruby before this, either through
yum
or by compiling it yourself.
# first update yum
sudo yum update -y
# remove any old versions of vim
sudo yum remove vim
# install extra deps
sudo yum install -y lua lua-devel luajit luajit-devel \
ctags mercurial python python-devel \
python3 python3-devel tcl-devel \
perl perl-devel perl-ExtUtils-ParseXS \
perl-ExtUtils-Xspp perl-ExtUtils-CBuilder
# symlink xsubpp (perl) from /usr/bin to the perl dir
sudo ln -s /usr/bin/xsubpp /usr/share/perl5/ExtUtils/xsubpp
# use ~/src as our compile dir
mkdir -p ~/src && cd ~/src
# clone the vim repo
hg clone https://vim.googlecode.com/hg vim
# configure it
cd vim
./configure --enable-fail-if-missing \
--enable-luainterp --with-luajit \
--enable-perlinterp \
--enable-pythoninterp \
--enable-python3interp \
--enable-rubyinterp \
--enable-tclinterp \
--enable-multibyte \
--enable-fontset
# install it in /usr/share/vim/vim74
VIMRUNTIMEDIR=/usr/share/vim/vim74 sudo make install
And there you have it! That should install the supporting files to
/usr/share/vim/vim74
and the new Vim binary to /usr/local/bin/vim
.
The full Ansible script I've used here is available in my dotfiles.
I've been playing with Ansible recently. I recorded a screencast on how to bootstrap a new cloud server with it.