Monday 14 December 2015

emacs lisp

setq

set quoted value

(setq SYMBOL VALUE)
(setq global-mark-ring-max 50000)

load

executes a file of lisp code.
first tries to find FILE.elc then FILE.el then FILE

(load FILE NOERROR=Nil NOMESSAGE=Nil NOSUFFIX=Nil MUST-SUFFIX=Nil)
(load "$HOME/.emacs.d/module")

require

(require FEATURE FILENAME=Nil NOERROR=Nil)
(require 'volatile-highlights)

add-to-list

(add-to-list VARIABLE VALUE)
(add-to-list 'load-path "~/.emacs.d/personal")

add-hook

prepends a function to the hooked event

(add-hook HOOK FUNCTION APPEND=Nil LOCAL=Nil)
(add-hook 'prog-mode-hook 'linum-mode)

global-set-key

(global-set-key KEY COMMAND)
(global-set-key (kbd "C-x C-b") 'ibuffer)

define-key

(define-key KEYMAP KEY DEF)
(define-key dired-mode-map (kbd "e") 'wdired-change-to-wdired-mode)

defalias

define alias

(defalias SYMBOL DEFINITION DOCSTRING=Nil)
(defalias 'eb 'eval-buffer)

mapc

call function on every element in sequence

(mapc FUNCTION SEQUENCE)
(mapc 'load (directory-files "~/.emacs.d/custom" t ".*\.el"))

defun

define function

(defun NAME ARGLIST DOCSTRING=Nil DECL=Nil BODY)
(defun demo ()
    (message "Hello World" number string))

Saturday 28 November 2015

emacs motion

emacs motion

C-f: forward one char
C-b: backward one char
C-p: previous line
C-n: next line

C-a: beginning of line
C-e: end of line
M-f: forward one word
M-b: backward one word

C-v: forward one screen
M-v: backward one screen
M-a: beginning of sentence
M-e: end of sentence
C-l: center the screen
M-r: cycle point through top, middle and bottom of the screen
M-<: jump to the top of the buffer
M->: jump to the end of the buffer
M-g c: jump to the nth character
M-g l: jump to the nth line

C-M-f: forward over balanced expression (eg: braces in C++ code)
C-M-b: backward over balanced expression
C-M-k: delete balanced expression
C-M-<SPC> or C-M-@: mark balanced expression

emacs ibuffer

ibuffer

In ~/.emacs.d/init.el:

;; replace `list-buffers` with `ibuffer`
(global-set-key (kbd "C-x C-b") 'ibuffer)

Open ibuffer by C-x C-b

Create filters:

/m: filter by a major mode
/n: filter by buffer name.
/c: filter by buffer content.
/f: filter by filename
/>: filter by buffer size
/<: filter by buffer size
//: remove all filters in effect

Filtered groups:

/g: create a filter group from filters
TAB: move to next filter group
M-p: move to previous filter group
/\: remove all active filter groups
/S: save the current groups with a name
/R: restore previously saved groups
/X: delete previously saved groups

Every time you open a file which matches a filter it will appear under the group

o on a file will open that file and switch focus to it
C-o on a file will open that file and leave focus in ibuffer
C-x o switches focus to the other window

Saturday 7 November 2015

Create a bootable USB from an ISO using dd on the Linux command line

Install syslinux, a suite of utilities which ensures the iso image is in SYSLINUX format rather than ISOLINUX

    $ sudo apt-get install syslinux

Convert the iso image to SYSLINUX format

    $ isohybrid /path/image.iso 

Locate the USB device 

    $ lsblk
    sdb         8:16   1   3.8G  0 disk 
    └─sdb1      8:17   1   3.8G  0 part /media/user/usb_disk

Unmount the USB device

    $ sudo umount /dev/sdb1

Ensure it is indeed unmounted

    $ lsblk
    sdb         8:16   1   3.8G  0 disk 
    └─sdb1      8:17   1   3.8G  0 part 

Copy the ISO image onto the USB deisk

    $ sudo dd if=/path/image.iso of=/dev/sdb1

Wednesday 28 October 2015

Qt: Updating styles based on dynamic properties

#include <QApplication>
#include <QMainWindow>
#include <QVBoxLayout>
#include <QLabel>
#include <QPushButton>
#include <QStyle>
#include <QDebug>

class App : public QObject
{
    Q_OBJECT
public:
    enum Alert
    {
        None,
        Warning,
        Critical
    };
    Q_ENUM(Alert);

    App(int argc, char** argv)
        : app(argc, argv)
    {}

    int exec()
    {
        window.setCentralWidget(&main);

        label.setText("hello world");
        label.setProperty("alert", QVariant::fromValue(None));

        button.setText("alert");

        QObject::connect(&button, &QPushButton::clicked, [this]()
            {
                label.setProperty("alert", QVariant::fromValue(Critical));
                label.setProperty("foo",   false);

                label.style()->unpolish(&label);
                label.style()->polish(&label);
                label.update();
            });

        layout.addWidget(&label);
        layout.addWidget(&button);
        main.setLayout(&layout);

        app.setStyleSheet(R"(
            QLabel[alert="None"]                { color: green; } 
            QLabel[alert="Warning"]             { color: blue;  }
            QLabel[alert="Critical"][foo=true]  { color: red;     }
            QLabel[alert="Critical"][foo=false] { color: magenta; }
        )");

        window.show();
        return app.exec();
    }

    QApplication app;
    QMainWindow  window;
    QWidget      main;
    QLabel       label;
    QPushButton  button;
    QVBoxLayout  layout;
};

int main(int argc, char** argv)
{
    return App(argc, argv).exec();

}


Tuesday 6 October 2015

Gnome - change default application for text files

xdg-mime query default text/plain
xdg-mime default sublime_text.desktop text/plain

xdg-mime query filetype application/x-shellscript
xdg-mime query default application/x-shellscript

Wednesday 19 August 2015

Send email from script

Install ssmtp:

    $ sudo apt-get install ssmtp

Edit the ssmtp config file:

    $ sudo vim /etc/ssmtp/ssmtp.conf

Enter this in the file:

root=username@gmail.com
mailhub=smtp.gmail.com:465
rewriteDomain=gmail.com
AuthUser=username
AuthPass=password (create a app-specific password in google accounts)
FromLineOverride=YES
UseTLS=YES

Enter the email address of the person who will receive your email:

    $ ssmtp recepient_name@gmail.com

Now enter this:

To: recipient_name@gmail.com
From: username@gmail.com
Subject: Sent from a terminal!

Your content goes here. Lorem ipsum dolor sit amet, consectetur adipisicing.
(Notice the blank space between the subject and the body.)

To send the email: Ctrl + D

You can also save the text mentioned in Point 5 into a text file and send it using:

    $ ssmtp recipient_name@gmail.com < filename.txt

http://askubuntu.com/questions/12917/how-to-send-mail-from-the-command-line

Friday 7 August 2015

Supervisord & Rundeck

supervisord

install

$ sudo easy_install supervisor

generate SHA-1 hash of password to be used for TCP access

$ echo -n password | sha1sum | awk '{print $1}'

enable TCP access

sudo vim /etc/supervisor/supervisord.conf

[inet_http_server]
port = 127.0.0.1:9001
username = user
password = {SHA}1235678

configure supervisorctl command line access (note password cannot be SHA hash, has to be plaintext)

[supervisorctl]
serverurl=unix:///var/run/supervisor.sock
serverurl=http://localhost:9001
username = user
password = abcdef

add a program

sudo vim /etc/supervisor/conf.d/app_example.conf

[program:app_example]
command=app_example
directory=/path/to/app
autostart:false
autorestart:false
startsecs:5
startretries:3
user:prod
redirect_stderr:true
stdout_logfile:/path/to/app/logfile.log
stdout_logfile_maxbytes:1000GB

supervisorctl - enter interactive mode

supervisorctl -s http://localhost:9001 -u user -p password

start/stop

    supervisorctl -s http://localhost:9001 -u user -p password start group:app

reread/restart/update

supervisorctl -s http://localhost:9001 -u user -p password update (or reread, restart)

reread just reads config changes, but doesn’t restart any affected processes
restart restarts the names process without loading any config changes
update rereads and restarts apps with changed configuration

rundeck

download and install from http://rundeck.org/downloads.html

add user to rundeck group

$ sudo usermod -a -G rundeck steve

add write permissions to rundeck group

$ sudo chmod g+w -R /var/rundeck

Friday 24 July 2015

Postgres

Postgres

install server

sudo apt-get install postgresql postgresql-contrib

install client

sudo apt-get install postgresql-client libpqxx-dev pgadmin3

configure server

As user postgres, run psql, connecting to database postgres

sudo -u postgres psql postgres

In the psql shell, set the postgres user’s password, and then press ctrl-d to exit the psql shell

\password postgres

create a new user, with an associated database

as user postgres, run createuser to create a new user dev

sudo -u postgres createuser -D -A -P dev

the options are:

  • -D: no database creation rights
  • -A: no add user rights
  • -P: ask for password

as user postgres, run createdb to create a new database devbd owned by user dev

sudo -u postgres createdb -O dev devdb

set the new user’s password

sudo -u postgres psql

\password dev
\password prod

install server instrumentation

as user postgres, create the adminpack extension

sudo -u postgres psql
CREATE EXTENSION adminpack;

change server authentication method

default authentication is peer. peer authentication obtains the client’s operating system user name from the kernel and uses it as the allowed database user name. This only works for local connections.

change to md5, which is password-based authentication, with the password sent over the connection as a md5 hash.

sudo vi /etc/postgresql/9.3/main/pg_hba.conf

change the line

# Database administrative login by Unix domain socket
local   all             postgres                                peer

to

# Database administrative login by Unix domain socket
local   all             postgres                                md5    

get postgres to reload the config

sudo /etc/init.d/postgresql reload

Wednesday 3 June 2015

GNU make variables

$@ - target's filename
$< - name of the first prerequisite
$? - list of all prerequisites newer than target
$^ - list of all unique prerequisites
$+ - list of all prerequisites, including duplicates (useful for linking)
$| - list of all order-only prerequisites
$* - stem; the part of the filename that matched the ‘%’ in the target pattern

$(@D) - directory part of the target (if no '/' appears, it is '.')
$(@F) - filename patr of the target (equivalent to $(notdir $@))

$(<D) - directory part of the first prerequisite
$(<F) - filename part of the first prerequisite

$(?D) - directory parts of the list of all prerequisites newer than target
$(?F) - filename parts of the list of all prerequisites newer than target

$(^D) - directory parts of the list of all unique prerequisites
$(^F) - filename parts of the list of all unique prerequisites

$(+D) - directory parts of the list of all prerequisites, including duplicates
$(+F) - filename parts of the list of all prerequisites, including duplicates

$(*D) - directory part of the stem
$(*F) - filename part of the stem


Tuesday 2 June 2015

CheckInstall

CheckInstall keeps track of all the files created when installing from source ($ make install), builds a standard binary package and installs it using the system package management software (apt / yum etc), allowing you to later uninstall it

 tar -zxvf source-app.tar.gz;
 cd source/ ;
 ./configure;
 make;
 sudo checkinstall make install;

https://wiki.debian.org/CheckInstall

Thursday 14 May 2015

Convert an enum class to its underlying_type

Generic helper function which takes any enum value and returns that value cast to its integral representation.

template<typename E>
constexpr auto to_integral(E e) -> typename std::underlying_type<E>::type 
{
   return static_cast<typename std::underlying_type<E>::type>(e);
}

Since it is constexpr it can be used as follows:

std::array<int, to_integral(my_fields::field)> b;

http://stackoverflow.com/questions/14589417/can-an-enum-class-be-converted-to-the-underlying-type

Thursday 9 April 2015

Ubuntu terminal tab colors

This sets dark tab colors, except for the active tab, which is higlighted

$ vim ~/.config/gtk-3.0/gtk.css

TerminalWindow .notebook {
    background-color: shade (#333333, 1.02);
    background-image: none;
    border-radius: 3px;
    padding: 2px;
    background-clip: border-box;
    border-color: shade (#333333, 0.82);
    border-width: 1px;
    border-style: solid;
    /*box-shadow: inset 0 1px shade (#AEA79F, 1.1);*/
    /*font-weight: 300;*/

}

TerminalWindow .notebook tab {
    background-image: none;
    background-color: #333333;
    border-style: solid;
    border-image: -gtk-gradient (linear, left top, left bottom,
                                 from (alpha (shade (#333333, 0.9), 0.0)),
                                 to (shade (#333333, 0.9))) 1;
    border-image-width: 0 1px;
    border-color: transparent;
    border-width: 0;
    box-shadow: none;
    /*color: shade (@fg_color, 1.2);*/
    color: #AEA79F;
}

TerminalWindow .notebook tab:active {
    border-color: shade (#333333, 0.82);
    border-style: solid;
    border-width: 1px;
    background-color: shade (#AEA79F, 1.02);
    background-image: none;
    /*box-shadow: inset 0 1px shade (#AEA79F, 1.1);*/

    color: #333333;
}

Sunday 15 March 2015

Pandas: merge 2 csv files of market data and plot the spread

import pandas as pd
import numpy as np
from datetime import datetime

%matplotlib inline

# load the csv files into pandas
def read_csv(filename):
    return pd.read_csv(
        filename, 
        dtype = {
            'bid_vol'  : np.float64, 
            'bid_price': np.float64, 
            'ask_vol'  : np.float64, 
            'ask_price': np.float64
        }, 
        na_values=['nan'], 
        index_col='time', 
        parse_dates=['time'], 
        date_parser=lambda x: datetime.strptime(x[:15], "%H:%M:%S.%f"))
df1 = read_csv('mkt1.best')
df1 = read_csv('mkt2.best')

# since both dataframes have the same column names for price data we
#   need to create a multiindex using the instrument id
def create_time_and_id_index(dfs):
    # appends all the dataframes into one big dataframe
    out = dfs.pop(0)
    for df in dfs:
        out = out.append(df)
    # add 'id' to the index
    out = out.set_index('id', append=True)
    # sort on timestamp
    out = out.sort()
    # pivot instr_id from the row index to the column index, leaving only timestamp as the row index
    out = out.unstack()
    # the times in the dataframes may not match up, so if we add them together, pandas will add NAN
    #  values for the other columns, so forward fill
    out = out.ffill()
    # reshuffle the column index so that instr_id is the top level, and the other column labels are the second level
    out = out.swaplevel(0,1,axis=1)
    # resort the column labels so that columns are grouped by instr_id
    out = out.sort(axis=1)
    return out

best = create_time_and_id_index([df1, df2])

# create spread columns
best['sell_spread'] = best[mkt2].ask_price - best.[mkt1].bid_price
best['buy_spread']  = best[mkt1].ask_price - best.[mkt2].bid_price

# plot the results!
best.plot(y='sell_spread', figsize=(20, 8))

Bash tab completion example

#!/bin/bash

_apps()
{
echo $(cat ${APPS} | awk '{print $1}' | grep -v -e '^#\|^$')
}

_servers()
{
echo $(cat ${SERVERS} | awk '{print $2}' | sort -u | cut -f2 -d@)
}

_options()
{
echo "--help --verbose --validate --quiet --server"
}

_commands()
{
echo "status start stop restart kill version config"
}

_contains()
{
  local e
for e in ${@:2}; do
if [[ "$e" == "$1" ]]; then
echo 1
return 0
fi
done
  echo 0
  return 1
}

_complete()
{
    local prev_cmd="${COMP_WORDS[COMP_CWORD-1]}"
    local curr_cmd="${COMP_WORDS[COMP_CWORD]}"

    if [[ ${prev_cmd} == "--server" ]]; then
        COMPREPLY=( $(compgen -W "$(_servers)" -- ${curr_cmd}) )
        return 0
    fi

    if [[ ${curr_cmd} == -* ]]; then
        COMPREPLY=( $(compgen -W "$(_options)" -- ${curr_cmd}) )
        return 0
    fi

    # previous command was an app name, so show commands
    if [[ $(_contains "${prev_cmd}" "$(_apps)") -eq 1 ]]; then
        COMPREPLY=( $(compgen -W "$(_commands)" -- ${curr_cmd}) )
        return 0
    fi

    # otherwise try match an app name
    COMPREPLY=( $(compgen -W "$(_apps)" -- ${curr_cmd}) )
}

_main()
{
complete -F _complete cmd
}
_main

Tuesday 10 March 2015

C++11 - Unevaluated operands

Operands of sizeof, typeid, decltype and noexcept are never evaluated

We therefore only need a declaration, not the definition, to use a function or object's name in these contexts

std::declval<T>()  returns T&&
std::declval<T&>() returns T&

decltype( foo(std::declval<T>()) ) returns foo's return type when foo is called with T&&

declval allows us to provide a declaration without having to evaluate the expression (ie: in an unevaluated context) - useful for SFINAE etc

Example: testing for copy-assignability

template<class T>
class is_copy_assignable
{
    template<class U, class=decltype(declval<U&>()=declval<const U&>())>
    static true_type try_assignment(U&&);

    template<class U>
    static false_type try_assignment(...); // catch-all fallback

public:
    using type = decltype(try_assignment(declval<T>()));
};

How this works:

try_assignment(...) will match anything, but is also always the worst match, so if the other try_assignment can match, it will.

type will be the return type of try_assignment, which will either be true_type or false_type

the true_type overload will only work if the expression U& = const U& is valid - ie: if it is copy assignable

We use a second template parameter to allow SFINAE to kick in. It is unnamed because we only use it for SFINAE.

Example: testing for copy-assignability, and requiring an lvalue reference return type

The above example doesn't force a requirement on the copy assignment returning an lvalue reference.

If we assign an alias template to the returned type:

template<class T>
using copy_assignment_t = decltype(declval<T&>() = declval<const T&>());

We can then check whether that is a T& in a SFINAE specialisation

template<class T, class=void>
struct is_copy_assignable 
    : std::false_type {};

template<class T>
struct is_copy_assignable<T, void_t<copy_assignment_t<T>>>
    : std::is_same<copy_assignment_t<T>,T&> {};

Monday 19 January 2015

find files older than today and zip them up with the date as part of the extension

1. find files older than today in a given directory with a given extension

$ find -mtime +1 ${DIR} -name "*.${EXT}"

2. calculate the last modified time (seconds since epoch)

$ MOD_SECS=$(stat -c%Y ${FILE})

3. convert the seconds since epoch into a human readable date format

$ MOD_DATE=$(date +\%Y-\%m-\%d --date="@${MOD_SECS}")

4. create a gzip file with the suffix including the date when the file was last modified

$ gzip -S .${MOD_DATE}.gz ${FILE}

5. putting it all together

for FILE in $(find ${DIR} -mtime +1 -name "*.${EXT}"); do
    MOD_SECS=$(stat -c%Y ${FILE})
    MOD_DATE=$(date +\%Y-\%m-\%d --date="@${MOD_SECS}")
    gzip -S .${MOD_DATE}.gz ${FILE}
done

6. as a script:

#!/bin/bash

if [ "$#" -ne 2 ]; then
    echo "Usage: $0 dir ext"
    exit 1
fi

DIR=$1
EXT=$2

for FILE in $(find ${DIR} -mtime +1 -name "*.${EXT}"); do
    MOD_SECS=$(stat -c%Y ${FILE})
    MOD_DATE=$(date +\%Y-\%m-\%d --date="@${MOD_SECS}")
    gzip -S .${MOD_DATE}.gz ${FILE}
done

Tuesday 6 January 2015

bash command line parsing

We want to be able to mix both optional flags, optional arguments and positional arguments

optional flags: getopts character, not followed by a ':'
optional arguments: getopts character, followed by a ':' (which means "take an argument"
positional arguments: after the getopts, use $OPTIND which is the index of the last option getopts parsed.

$ script.sh [options] ARG1 ARG2

#!/bin/bash

usage() 

    echo "Usage: $0 [-a foo] [-b] ARG1 ARG2" 1>&2;
    exit 1
}

while getopts ":a:bh" o; do
    case "${o}" in
        a) a=${OPTARG};;
        b) b=YES;; # turn on flag
        h) usage ;; # display help
    esac
done

# store positional arguments
ARG1=${@:$OPTIND:1}
ARG2=${@:$OPTIND+1:1}

# check positional arguments have been supplied
if [ -z "${ARG1}" ] || [ -z "${ARG2}" ]; then
    usage
fi

# display the results
echo a=${a}
echo b=${b}
echo ARG1=${ARG1}
echo ARG2=${ARG2}