Simplified getopt for lua

Lua doesn’t include getopt. I have written this very simple implementation. It is actually a simplified version of AlternativeGetOpt. It is usable but absolutely not user-proof! Good enough for your own scripts though.

function getopt(o)
  local p = {}
  for k,v in ipairs(arg) do
    if v:byte(1) == 45 then
      local l = v:sub(2,2)
      if o:match(l) then
        p[l] = arg[k+1]
      else
        p[l] = true
      end
    end
  end
  return p
end

You can test for example with the following main function:

function main()
   local opts = getopt("up")
   local user = opts.u and opts.u or "default"
   local pass = opts.p and opts.p or "secret"
   local root = opts.a and true or false
   print(user, pass, root)
end

Usage examples:

$ getopt
default	secret	false
$ getopt -u lyderic
lyderic	secret	false
$ getopt -u lyderic -p password
lyderic	password	false
$ getopt -a -u lyderic -p password
lyderic	password	true
$ getopt -a -u lyderic -w
lyderic	secret	true

The full code is on github: https://github.com/lyderic/scripts/blob/master/getopt.lua

gvim on Ubuntu

I set up this script to build gvim on Ubuntu. It presuppose that you git cloned the vim sources in /opt/src/vim.

#!/bin/sh

sudo apt-get update && sudo apt-get upgrade

sudo apt-get install libncurses5-dev libgnome2-dev \ 
  libgnomeui-dev libgtk2.0-dev libatk1.0-dev \
  libbonoboui2-dev libcairo2-dev libx11-dev \
  libxpm-dev libxt-dev

cd /opt/src/vim
make distclean
sudo make uninstall
git pull

./configure --with-compiledby=lyderic
  --with-features=huge --enable-luainterp \
  --with-lua-prefix=/usr/local \
  --enable-fail-if-missing --enable-gui=gnome2

make -j $(nproc)
sudo make install

git from source on Centos 7

As for many packages, git is fairly old on CentOS 7. The version they provide lacks a feature that I rely on, namely the -C switch, to be able to call git anywhere, without having to cd to the git directory first.

These are the steps I took to build git on CentOS 7:

yum -y install gcc make gettext-devel openssl-devel perl-devel curl-devel expat-devel
curl https://www.kernel.org/pub/software/scm/git/git-2.10.2.tar.gz | tar xzf -
cd git-2.10.2
make prefix=/usr/local -j $(nproc)
make install prefix=/usr/local
git --version

Continue your loops in lua

I am so used to the continue word in Java and C that I was surprised to see it absent in lua.

It is however relatively easy to implement it with a good ol’ goto.

Here is a (rather stupid) example. We get a directory listing and we filter out the hidden files (starting with a dot):

local h = io.popen("ls -a")
for line in h:lines() do
   if string.match(line, "^%.") then goto continue end
   print(line)
   ::continue::
end
h:close()

 

Ternary operator in lua

In Java, I very often have to do the following, to mark the plural when needed:

System.out.printf("Delivered: %d item%s", n, n > 1 ? "s", "");

In Lua, there is no ternary operator, so this kind of elegant syntax might be compromised in this situation. Fortunately, there is an as nice workaround:

print(string.format("Delivered: %d item%s", n > 1 and "s" or ""))

Thanks to hisham.hm

vim with lua

This is a log of the steps I took to compile vim with lua support. I wrapped everything up in a script that I called ‘luavim’. I have tested it on CentOS/RedHat, Debian/Ubuntu and Alpine Linux.

Dependencies are:
Libraries: libreadline, libcurses, glibc/musl
Packages: git, gcc, make

To install the dependencies for Alpine Linux, you can run:

# apk add musl-dev git gcc make readline-dev ncurses-dev

To install the dependencies for Debian/Ubuntu, you can run:

# apt install gcc make libreadline-dev libncurses-dev

To install the dependencies for CentOS/RedHat, you can run:

# yum install git gcc make readline-devel ncurses-devel

Everything gets installed into /usr/local. The user running this script must have sudo.

This is the script:

#!/bin/sh

operator=$(whoami)
srcdir=/opt/src

main() {

   if [ -z $1 ]
   then
      usage
   fi

   init

   case "$1" in
      a) buildlua; buildvim ;;
      l) buildlua ;;
      v) buildvim ;;
      r) reset ;;
      *) echo "invalid"; usage ;;
   esac
}

init() {
   if [ ! -d ${srcdir} ]
   then
      sudo mkdir -pv ${srcdir}
   fi
   sudo chown -R ${operator} ${srcdir}
}

buildlua() {

   cd ${srcdir}
   if [ ! -d lua ]
   then
      echo "Cloning github lua repository..."
      git clone https://github.com/lua/lua.git
   fi

   cd ${srcdir}/lua
   make clean
   git pull
   sudo make uninstall

   make linux -j 4
   sudo make install

   lua -v

}

buildvim() {

   cd ${srcdir}
   if [ ! -d vim ]
   then
      echo "Cloning github lua repository..."
      git clone https://github.com/vim/vim.git
   fi
   
   cd ${srcdir}/vim
   make clean
   git pull

   ./configure \
   --with-compiledby=lyderic \
   --with-features=huge \
   --enable-luainterp \
   --with-lua-prefix=/usr/local \
   --enable-fail-if-missing

   sudo make uninstall
   make -j 4
   sudo make install

}

reset() {
   cd ${srcdir}/lua
   sudo make uninstall
   cd ${srcdir}/vim
   sudo make uninstall
   sudo rm -rfv ${srcdir}
}

usage() {
   echo "Usage: $(basename $0) "
   echo "Actions:"
   echo " a  build lua and vim"
   echo " l  build lua only"
   echo " v  build vim only"
   echo " r  wipes everything"
   exit 2
}

main $@

docker-compose

I have started to use docker-compose and I really like it.

Some notes :

  1. It is easy to install. I used this (on CentOS 7):
    $ sudo -i
    # curl -L https://github.com/docker/compose/releases/download/1.9.0-rc2/docker-compose-`uname -s`-`uname -m` > /usr/local/bin/docker-compose
    # chmod +x /usr/local/bin/docker-compose
  2. selinux
    I have to disable it on CentOS otherwise haproxy doesn’t forward to containers listening on ports TCP/8000+. I run:

    $ sudo -i
    # sed -i -e 's/SELINUX=enforcing/SELINUX=disabled/' /etc/sysconfig/selinux
    # cat /etc/sysconfig/selinux

Next up, I will document how to automate this with ansible.