abhi's logbook

Adventures in coding and coding for adventures.

Code to Update Reminders app from Emacs

(defun ay/org-update-reminder-lists ()
  (interactive)
  (ay/org-update-buy-list)
  (ay/org-update-corrie-list)
  (ay/org-update-home-list))

(defun ay/org-update-morning-list ()
  (interactive)
  (ns-do-applescript
   (concat
    "tell application \"Reminders\"\n"
    "tell list \"Morning\" to delete reminders\n"
    "tell list \"Morning\"\n"
    (mapconcat (lambda (title) (format "make new reminder with properties {name:\"%s\"}" title))
               (org-map-entries (lambda () (nth 4 (org-heading-components)))
                                "morning+TODO=\"NEXT-ACTION\"" 'agenda) "\n")
    "\nend tell\n"
    "end tell\n")))

(defun ay/org-update-reading-list ()
  (interactive)
  (ns-do-applescript
   (concat
    "tell application \"Reminders\"\n"
    "tell list \"Reading\" to delete reminders\n"
    "tell list \"Reading\"\n"
    (mapconcat (lambda (title) (format "make new reminder with properties {name:\"%s\"}" title))
               (org-map-entries (lambda () (nth 4 (org-heading-components)))
                                "reading" 'agenda) "\n")
    "\nend tell\n"
    "end tell\n")))

(defun ay/org-update-buy-list ()
  (interactive)
  (ns-do-applescript
   (concat
    "tell application \"Reminders\"\n"
    "tell list \"Buy\" to delete reminders\n"
    "tell list \"Buy\"\n"
    (mapconcat (lambda (title) (format "make new reminder with properties {name:\"%s\"}" title))
               (org-map-entries (lambda () (nth 4 (org-heading-components)))
                                "buy+TODO=\"NEXT-ACTION\"" 'agenda) "\n")
    "\nend tell\n"
    "end tell\n")))

(defun ay/org-update-corrie-list ()
  (interactive)
  (ns-do-applescript
   (concat
    "tell application \"Reminders\"\n"
    "tell list \"Corrie\" to delete reminders\n"
    "tell list \"Corrie\"\n"
    (mapconcat (lambda (title) (format "make new reminder with properties {name:\"%s\"}" title))
               (org-map-entries (lambda () (nth 4 (org-heading-components)))
                                "corrie+TODO=\"NEXT-ACTION\"" 'agenda) "\n")
    "\nend tell\n"
    "end tell\n")))

(defun ay/org-update-home-list ()
  (interactive)
  (ns-do-applescript
   (concat
    "tell application \"Reminders\"\n"
    "tell list \"Home\" to delete reminders\n"
    "tell list \"Home\"\n"
    (mapconcat (lambda (title)
                 (format "make new reminder with properties {name:\"%s\"}" title))
               (org-map-entries (lambda () (nth 4 (org-heading-components)))
                                "home" 'agenda) "\n")
    "\nend tell\n"
    "end tell\n")))

Using watchman to allow the generation of this site. Hi

DayOne Todo

I need to write a better org-mode to DayOne exporter. Right now the way org-mode exports data is pretty gross and I think there needs to be a better mechanism by which this happens. I don’t really care much for a command line tool as much as a tool which will allow me to write correct output.

  • OrgMode output to DayOne.
  • Output to DayOne should be in a good form which doesn’t throw a bunch of random HTML.
  • Should be clean and easy to read.

Beautiful shot at Corrie’s house.

Jekyll Branch Deployment

A tool which deploys a branch to a separate staging environments which is tied to Github.

The flow should be the following:

  • Git commit is pushed.
  • Post receive hook is received and we take those to build alternate the site and deploy it. Should do so for pull requests as well.
  • Take all the branches and push it to different stage environments

This can be achieved in the following way:

  • Docker image which contains:
    • Jekyll
    • Post-Hook Receiving App
    • Nginx
  • A post hook is received.
  • App essentially keeps track of all the branches and their commits.
    • If a branch is created or updated then it causes a regeneration.
    • There should be a folder generated in static.
      • These folders should be the subdomains that are generated.

Working on a book. I started using a software called Ulysses. It seems like a good balance between plain text and having the ability to organize things via WYSWYG. The combination is great.

I love Emacs org-mode but sometimes I am more of a visual organizer. I like to see things and manipulate them and jump to different portions. I feel like this is a good balance.

I will still continue using org-mode but it will not be for large writing projects because I struggle to do so in Emacs. Or maybe this will be a trail in using an existing tool to do the writing and not Emacs for once. Maybe I’ll run back to it.

Notes on developing my DayOne to blog post generator for Jekyll. This is the following and what I want to still accomplish:

  • [X] Have a simple thing generator which creates the posts and does some form of syntax highlighting.
  • [X] Have a blog page which shows all the content for that post.
  • [X] Have a well designed blog page.
  • [ ] Be able to filter down to the tags level.
  • [ ] Have an automated way of watching for changes to the DayOne folder and triggering a rebuild of the website based on that.
  • [ ] Effective SEO of the content.

Overall I am happy that I can finally write posts here and have them generate appropriately in my blog.

Introduction

Unix is like a war chest full of different tools to accomplish
different things. They can work together to get your job done.
They can be faster than the equivalent GUI tools.

The goal of this document is to show some of the power that Unix
posesses and hopefully to transfer some of that knowledge so others
can be just as productive with this wonderful system which has
largely stood the legacy of time.

Commands

Command Description
comm Compares two files. It allows you to see what is available in one file, the second file or both files. It is useful to see information on unions of files.

Setting up a new machine

I’m sure I can do this a better way using chef-solo or something but I
like to keep things simple.

passwd
/etc/sudoers
adduser abhi
apt-get update
apt-get upgrade
apt-get install zsh tmux emacs vim sudo git

git clone https://github.com/abhiyerra/dotfiles
cd dotfiles
sh dotfiler.sh

I really like Dropbox. It’s a convienient way to sync all your
computers and makes it quite easy to get started. However, the thing
that bugs me the most is keeping my dotfiles in sync as I usualyl
forget to sync between computers when I change
them. Thanksfully, Dropbox makes this easier.

  1. Create a directory in your Dropbox folder.
  2. Move your dotfiles from $HOME to that folder. Change the prefix . with _.
  3. Add this file (I named it dotfiler.sh, but you can name it whatever you want)

    #!/bin/sh

    for file in *
    do
    ln -s -n -f pwd/$file $HOME/${file/#
    /.}
    done

Now whenever you have a new machine just run the script in your
dotfiles directory. This should keep all your dotfiles in sync
whatever computer you are using and make setting up a new environment
less painful.

If you also added a .profile and .bashrc or .zshrc file make
sure to take your platform into account i.e., Linux, Mac OS X. You can
also run the script whenever you add a new file.

Zsh

cd -

Move back to the previous directory you were in.

[email protected]:~/Dropbox $ cd ~/.emacs.d/plugins/org-mode
[email protected]:~/.emacs.d/plugins/org-mode $ cd -
~/Dropbox
[email protected]:~/Dropbox $

!$

Gives the last argument from previously run command.

[email protected]:~/Dropbox $ mv junk ~/.emacs.d/plugins/org-mode
[email protected]: $ cd !$
[email protected]:~/.emacs.d/plugins/org-mode $

Network Utilities

lsof

Process running on a port

$ lsof -i :3000
COMMAND  PID   USER   FD   TYPE             DEVICE SIZE/OFF NODE NAME
ruby    7634 ayerra   12u  IPv4 0x3a21119dc10aed27      0t0  TCP *:hbci (LISTEN)

ngrep

A super useful tool to sniff network traffic. Allows you to see what
is going in and out of your network device.

[email protected]:~ $ sudo ngrep
Password:
interface: en0 (192.168.1.0/255.255.255.0)
#
T 89.16.176.16:6667 -> 192.168.1.104:63781 [AP]
  :[email protected] PRIVMSG #emacs :+takes me back to list..
##
T 89.16.176.16:6667 -> 192.168.1.104:63781 [AP]
  :[email protected] PRIVMSG #emacs :+looks like it's in some monitored list but I can't figure where to look..
##
U 192.168.1.104:17500 -> 255.255.255.255:17500
  {"host_int": 89902014, "version": [1, 8], "displayname": "89902014", "port": 17500, "namespaces": [53605312, 4575490, 8623931, 69308427, 7943213, 98397390]}
#
U 192.168.1.104:17500 -> 192.168.1.255:17500
  {"host_int": 89902014, "version": [1, 8], "displayname": "89902014", "port": 17500, "namespaces": [53605312, 4575490, 8623931, 69308427, 7943213, 98397390]}
#
T 89.16.176.16:6667 -> 192.168.1.104:63781 [AP]
  :[email protected]/rking PRIVMSG #ruby :+Hehe, noobs unite!..

Here you see the packets from my connection to IRC being listed.

ssh

Connect without a Password

cd ~/.ssh
# Will ask for a ssh key name
ssh-keygen -t dsa
# Copy to remote host
scp ~/.ssh/<nameoffile>.pub remote:~/.ssh/authorized_keys2
ssh-add <nameoffile>

iptables

Block a port

iptables -A INPUT -j DROP -p tcp --destination-port 80 -i eth0

Introduction

I converted to Emacs at the end of 2010 when I joined my first real
engineering job after completing college.

Emacs is not really an “editor” per se. It is a Lisp Machine posing as
an editor. Considering its origins at the MIT AI Labs and Richard
Stallman’s involvement the legacy can be seen in the way it functions.

Most text editors bring you down to the way they want to function
based on what the original authors had in mind. There might be
flexiblity but it is more than likely that it is difficult to modify
the builtin structures to behave the way you want.

Emacs makes the distinction in that anything is customizable. There is
a thin layer of C code which basically just runs the Emacs Lisp.

I won’t recommend fully jumping into Emacs (i.e using ERC, Gnus and
all) start off small. Some of tools do show their age and certain
things are just plain painful to use because Emacs is single
threaded. I say start using org-mode and go from there.

Also, learn something new everyday, learn Emacs Lisp and add small
custom functionality. As an engineer you spend most of your time in
your editor so might as well make it behave to your command.

Commands

Keystroke Description
M-x align-regexp Select a region and pick a regex and it'll align based on that.
M-SPC Removes space around block of text and replace it with one space.
M-^ Join two lines removes spaces around it.
M-q fill-paragraph. Splits the columns into correct fill-column size.
M-t transpose two words
C-x ENT f Pick the correct encoding. I.e. unix removes ^M ^J ^L
C-x 4 a If you are in a ChangeLog file. This creates a new changelog item.
C-S-[Backspace] Kills the current line.
C-s C-w Search for the word at mark. Can keep adding C-w to add more words.
M-x flush-lines RET ^$ RET Remove blank lines

Paste and Indent

This allows you to paste and automatically indent the region correctly.

(defun yank-and-indent ()
  "Yank and then indent the newly formed region according to mode."
  (interactive)
  (yank)
  (call-interactively 'indent-region))
(global-set-key "\C-y" 'yank-and-indent)

Export org-mode file as a Batch Job

emacs --batch --eval "(setq org-export-headline-levels 6)" --visit=schedule.org --execute "(org-export-as-html nil nil nil nil t)"

Emacs Email

Mew

(add-to-list 'load-path "~/Dropbox/Mew")
(autoload 'mew "mew" nil t)
(autoload 'mew-send "mew" nil t)

;; Optional setup (Read Mail menu for Emacs 21):
(if (boundp 'read-mail-command)
    (setq read-mail-command 'mew))
;; Optional setup (e.g. C-xm for sending a message):
(autoload 'mew-user-agent-compose "mew" nil t)
(if (boundp 'mail-user-agent)
    (setq mail-user-agent 'mew-user-agent))
(if (fboundp 'define-mail-user-agent)
    (define-mail-user-agent
      'mew-user-agent
      'mew-user-agent-compose
      'mew-draft-send-message
      'mew-draft-kill
      'mew-send-hook))

(setq mew-config-alist
      '(("default"
         ("mailbox-type" . imap)
         ("proto" . "%")
         ("imap-server" . "imap.gmail.com")
         ("imap-ssl" . t)
         ("imap-user" . "[email protected]") ;; to be completed
         ("prog-ssl" . "/use/local/bin/stunnel")
         ("user" . "ykabhinav")
         ("mail-domain" . "gmail.com")
         ("name" . "Abhi Yerra")
         ("imap-delete" . nil)
         ("imap-size" . 0)
         ("smtp-ssl"    . t)
         ("smtp-ssl-port". "465")
         ("smtp-auth-list" . ("PLAIN" "LOGIN" "CRAM-MD5"))
         ("smtp-user"   . "[email protected]")
         ("smtp-server" . "smtp.gmail.com")
         ("inbox-folder" . "%INBOX")
         ("imap-friend-folder" . "%from")
         ("imap-trash-folder" . "%[Gmail]/All Mail"))))

(setq mew-use-unread-mark t)
(setq mew-delete-unread-mark-by-mark nil)

VM

Make sure that you have stunnel 4.33 or lower for the trunk version of
VM.

(add-to-list 'load-path "~/Dropbox/vm/lisp")
(require 'vm-autoloads)

(setq mail-user-agent 'vm-user-agent)

(setq vm-folder-directory "~/Mail")
(setq vm-primary-inbox "~/Mail/vminbox")
(setq vm-crash-box "~/Mail/inbox.crash.mbox")

(setq vm-imap-expunge-after-retrieving nil)

(setq vm-mutable-frames nil)
(setq vm-imap-account-alist
      '(("imap-ssl:imap.gmail.com:993:login:[email protected]:*" "gmail")))

(setq vm-primary-inbox "imap-ssl:imap.gmail.com:993:inbox:login:[email protected]:*")

(setq vm-debug t)
(setq vm-keep-imap-buffers t)
(setq vm-imap-log-sessions t)

(setq vm-use-menus 1)
(setq vm-stunnel-program "stunnel")

(setq send-mail-function 'smtpmail-send-it
      message-send-mail-function 'smtpmail-send-it
      smtpmail-starttls-credentials
      '(("smtp.gmail.com" 587 nil nil))
      smtpmail-auth-credentials
      (expand-file-name "~/.authinfo")
      smtpmail-default-smtp-server "smtp.gmail.com"
      smtpmail-smtp-server "smtp.gmail.com"
      smtpmail-smtp-service 587
      smtpmail-debug-info t)
(require 'smtpmail)

(setq mail-default-headers "From: Abhi Yerra <[email protected]>\n")


(setq  vm-mime-type-converter-alist
      '(("text/html" "text/plain" "elinks -dump /dev/stdin")
        ("message/delivery-status"  "text/plain")
        ("application/zip"  "text/plain" "listzip")
        ("application/x-zip-compressed"  "text/plain" "zipinfo /dev/stdin")
        ("application/x-www-form-urlencoded"  "text/plain")
        ("message/disposition-notification"  "text/plain")
        ("application/mac-binhex40" "application/octet-stream" "hexbin -s")))

(define-key vm-mode-map "#" 'vm-imap-synchronize)

BBDB

;; bbdb
(add-to-list 'load-path "~/.emacs.d/plugins/bbdb/lisp")
(require 'bbdb)
(require 'bbdb-gnus)
(bbdb-initialize 'gnus 'message)
(bbdb-insinuate-gnus)
(bbdb-insinuate-message)
(add-hook 'gnus-startup-hook 'bbdb-insinuate-gnus)
(setq bbdb-send-mail-style 'gnus)
(setq bbdb-complete-name-full-completion t)
(setq bbdb-completion-type 'primary-or-name)
(setq bbdb-complete-name-allow-cycling t)

Syncing with Google Contacts

At this point I’d recommend just using google-contacts.el. When I
first wrote this script the elisp script didn’t exist so I didn’t use
it. I think at this point this is obsolete code.

I store my contacts in Google because I love their sync service and I
use it with my iPhone all the time. Makes managing contacts quite
easy. I wanted my BBDB contacts to be synced. I discovered googlecl
which is a nifty command line way to access many Google services.

This allowed me to update my records.

(mapcar
 '(lambda (x)
    (bbdb-create-internal (first x) nil nil nil (second x)))
    (mapcar
     '(lambda (x) (split-string x ","))
     (process-lines "/usr/local/bin/google" "contacts" "list" "name,email")))

Placing a Call via Skype (on Mac)

BBDB 3.0 has an updated function called bbdb-dial-number. You can use
this to make calls using Skype on the Mac by interfacing with
AppleScript.

(setq bbdb-dial-function
      '(lambda (phone-number)
         (do-applescript
          (concat
           "tell application \"Skype\"\n"
           "send command \"CALL +" phone-number "\" script name \"Call from BBDB\"\n"
           "end tell"))))

Post to Jekyll

; Jekyll move to org-capture binding.
(defun new-blog-post (title)
  "Create a new Jekyll blog post."
  (interactive "sPost Title: ")
  (let ((draft-file (concat "~/Dropbox/docs/blogfiles/"
                            (format-time-string "%Y-%m-%d-")
                            (replace-regexp-in-string
                             " " "-" (downcase
                                      (replace-regexp-in-string
                                       "[^A-Za-z0-9 ]" "" title)))
                            ".org")))
    (find-file draft-file)
    (insert (format
             (concat "#+BEGIN_HTML\n"
                     "---\n"
                     "layout: post\n"
                     "title: %s\n"
                     "---\n"
                     "#+END_HTML\n"
                     "\n") title))))

NewsTicker

The three choices for NewsTicker w3, w3m, htmlr are mostly crappy in
the way they output html or don’t work with Emacs 23. A better
alternative is to output it using Lynx. Here is how to set up
NewsTicker to use Lynx to render the item buffer.

(defun lynx-renderer (start end &optional url charset)
  (interactive)
  (shell-command-on-region start end
   (format "lynx -force_html -dump -stdin %s" url)
   (current-buffer)))

(setq newsticker-html-renderer 'lynx-renderer)

Send Messages to Boxcar

I was bored and wanted to send something to my phone from emacs so I
wrote this. This sends a message to Boxcar. This can also likely
modifed to work with the Twilio API.

(defun send-region-to-boxcar (start end)
  (interactive "r")
  (let ((url-request-method "POST")
        (url-request-extra-headers `(("Content-Type" . "application/x-www-form-urlencoded")))

        (url-request-data (concat "email=INSERT_MD5_OF_EMAIL&Body=123" "&"
                                  "notification[from_screen_name]=c0rnbot" "&"
                                  "notification[message]=" (url-hexify-string (buffer-substring start end)))))
    (url-retrieve-synchronously
     "http://boxcar.io/devices/providers/8SF0X9Diup0m0cK1QmzZ/notifications")))


(global-set-key "\C-ct" 'send-region-to-boxcar)

Cron

If you want to include a cron task in your Emas this is the format to do it.

Here we check if a folder exists. Then we run a task at 10 am
conintuing at 30 minute intervals.

(if (file-exists-p "~/Dropbox/Public/Space")
    (run-at-time
     "10:00AM"
     3600
     '(lambda ()
        (start-process
         "space-photo-download"
         "*Space Photo Download*"
         "sh" (concat
               (getenv "HOME")
               "/Dropbox/Sites/abhiyerra.com/scripts/download_space_photo.sh")))))

Commit Messages

~/.gitconfig

The following is my ~/.gitconfig file which makes using git a bit
more enjoyable. It provides color on diffs, shortcuts for commonly
used commands and other goodies.

[user]
    email = [email protected]
    name = Abhi Yerra
[alias]
    ap = add -p
    cl = clone --recursive
    st = status
    stat = status -sb
    sb = show-branch
    ci = commit
    co = checkout
    ch = checkout
    chekcout = checkout
    br = branch
    df = diff
    dt = difftool -y
    lg = log -p --stat
    rev = rev-parse HEAD
    wc = whatchanged --stat
    wd = diff --word-diff
    up = remote -v update -p
    prb = pull --rebase
    sub = submodule
    subup = submodule update --init
    remotes = remote -v show
    remup = remote update --prune
    # remtrack = !git branch -vv | ruby -ne '$_ =~ /\s+([^\s]+)\s.*\[([^\]]+)/; branch, remote = $1, $2; `git show #{remote} 2>&1 >/dev/null`; puts "#{branch} -> #{remote}, remote_exists? = #{$?==0}";'
    m  = !B=$(git branch | grep '*' | awk '{print $2}') && R=$(git config branch.$B.remote) && RB=$(git config branch.$B.merge | cut -d/ -f3-) && git merge $R/$RB
    d  = !B=$(git branch | grep '*' | awk '{print $2}') && R=$(git config branch.$B.remote) && RB=$(git config branch.$B.merge | cut -d/ -f3-) && git wc $B..$R/$RB
    rd = !B=$(git branch | grep '*' | awk '{print $2}') && R=$(git config branch.$B.remote) && RB=$(git ) && git wc $R/$RB..$B
    human = name-rev --name-only --refs=refs/heads/*
    humin = name-rev --name-only --refs=refs/heads/* --stdi
    change-commits = "!f() { VAR=$1; OLD=$2; NEW=$3; shift 3; git filter-branch --env-filter \"if [[ $`echo $VAR` = \\\"$OLD\\\" ]]; then export $VAR=\\\"$NEW\\\"; fi\" [email protected]; }; f "
[color]
    ui = auto
    diff = auto
    status = auto
    branch = auto
    interactive = auto
    current = yellow reverse
    local = yellow
    remote = green
[color "diff"]
    whitespace = red reverse
    frag = cyan
    old = red bold
    new = green bold
[color "status"]
    added = green
    changed = yellow
    untracked = red
[core]
    excludesfile = ~/.gitignore-global
    whitespace=trailing-space,cr-at-eol
[apply]
    whitespace = nowarn
[push]
    default = tracking
[branch]
    autosetupmerge = true
[merge]
    stat = true
[status]
    submodulesummary = true
[mergetool]
        keepBackup = true
[github]
        user = abhiyerra
[filter "media"]
        clean = git-media-clean %f
        smudge = git-media-smudge %f

Branches

This will show the remote branches.

$ git branch -r

Adds a remote repo other then origin. Do a git-fetch to pull the
updated changes. This will allow you to track multiple repos at the
same time and merge from each which is pretty sweet.

$ git remote add linux-nfs git://linux-nfs.org/pub/nfs-2.6.git
$ git fetch linux-nfs

Say you are on a local branchname and you want to
push it to a remote server you can do it via the following.

$ git push -u origin branch_name

To delete that remote branch do:

$ git push origin :branch_name

This removes the remote branch without warning so use with care.

If you want to branch off a different remote branch do the following:

$ git checkout -b a-branch-that-tracks-a-remote --track origin/remote_branch

Set a remote branch for the current branch.

$ git branch --set-upstream-to upstream/master

Check how far behind or forward a branch is from remote

$ git branch -vv

Bisect

If there is a regression the best way to check at what commit the error
occured is through git-bisect

To start the process

$ git bisect start # starts the bisecting process
$ git bisect good <tag/commit>
# Picks a version where the error didn't occur
$ git bisect bad master # Start bisecting from current branch.

For each version see if it is bad do:

$ git bisect bad

At the end it will show where the error occured when doing this process.
will end the bisecting process.

$ git bisect reset

Logs and Blames

Shows the log with the diffs as well as what files have changed.

$ git log -p --stat

Adding Patches to Staging.

If you want to add individual patches from a file without adding the
whole file.

$ git add -p

Generate TAGS file using ctags

If I put this in my .git/hooks/post-commit it generates a TAGS file
after each commit.

$ git ls-files | xargs /usr/local/bin/ctags -e -a &> /dev/null &

Squashing commits

$ git remote update
$ git pull --rebase upstream master
$ git rebase -i upstream/master

Grepping commits

$ git log --grep=word

Have a branch with unrelated changes

I want to pull changes from say an old version of the project to my
current project but under a branch that is unrelated.

git remote add old <path>
git checkout -b old --track old/master
git remote rm old
git branch --set-upstream origin old
git push

Regex

Email

This is the perfect regex to detect email addresses. (Should be
all on one line. Split so it doesn’t break screen bounds.)

Cucumber

Some helpful links to understanding Cucumber.

FactoryGirl

Referencing defined models

developer = model!(%|developer: "#{developer_name}"|)

Testing Subdomain

Given /^I visit subdomain (.+)$/ do |sub|
  host! "#{sub}.#{TEST_DOMAIN}" #TEST_DOMAIN is defined in test.rb. In my case TEST_DOMAIN = 'example.com'
end

Scenarios

Feature: Addition
In order to avoid silly mistakes
As a math idiot
I want to be told the sum of two numbers

Scenario Outline: Add two numbers
Given I have entered <input_1> into the calculator
And I have entered <input_2> into the calculator
When I press <button>
Then the result should be <output> on the screen

Examples:
| input_1 | input_2 | button | output |
|      20 |      30 | add    |     50 |
|       2 |       5 | add    |      7 |
|       0 |      40 | add    |     40 |

Tables

Row Tables

| id | error |
|  1 | yes   |
|  2 | yes   |
|  3 | no    |

Given /^I have a spirit with the following attributes:$/ do |table|
  table.hashes.each do |attributes|
    Spirit.create!(attributes)
  end
end

Hash Table

| id    |   1 |
| error | yes |

Given /^I have a spirit with the following attributes:$/ do |table|
  table.rows_hash['id'].should == 1
end

JRuby

Cassandra Thrift Example

Here is how to connect to Cassandra using JRuby using the Java Thrift API.
I was a bit annoyed that the Ruby libraries were using native libraries so I wrote it using JRuby.

 1    require 'java'
 2    
 3    # All the files from cassandra/lib
 4    require 'lib/antlr-3.1.3.jar'
 5    require 'lib/apache-cassandra-0.6.1.jar'
 6    require 'lib/avro-1.2.0-dev.jar'
 7    require 'lib/clhm-production.jar'
 8    require 'lib/commons-cli-1.1.jar'
 9    require 'lib/commons-codec-1.2.jar'
10    require 'lib/commons-collections-3.2.1.jar'
11    require 'lib/commons-lang-2.4.jar'
12    require 'lib/google-collections-1.0.jar'
13    require 'lib/hadoop-core-0.20.1.jar'
14    require 'lib/high-scale-lib.jar'
15    require 'lib/ivy-2.1.0.jar'
16    require 'lib/jackson-core-asl-1.4.0.jar'
17    require 'lib/jackson-mapper-asl-1.4.0.jar'
18    require 'lib/jline-0.9.94.jar'
19    require 'lib/json-simple-1.1.jar'
20    require 'lib/libthrift-r917130.jar'
21    require 'lib/log4j-1.2.14.jar'
22    require 'lib/slf4j-api-1.5.8.jar'
23    require 'lib/slf4j-log4j12-1.5.8.jar'
24    
25    java_import org.apache.cassandra.thrift.Cassandra
26    java_import org.apache.cassandra.thrift.ColumnOrSuperColumn
27    java_import org.apache.cassandra.thrift.ColumnPath
28    java_import org.apache.cassandra.thrift.Column
29    java_import org.apache.cassandra.thrift.ColumnParent
30    java_import org.apache.cassandra.thrift.ConsistencyLevel
31    java_import org.apache.cassandra.thrift.InvalidRequestException
32    java_import org.apache.cassandra.thrift.NotFoundException
33    java_import org.apache.cassandra.thrift.TimedOutException
34    java_import org.apache.cassandra.thrift.UnavailableException
35    java_import org.apache.thrift.TException
36    java_import org.apache.thrift.protocol.TBinaryProtocol
37    java_import org.apache.thrift.protocol.TProtocol
38    java_import org.apache.thrift.transport.TSocket
39    java_import org.apache.thrift.transport.TTransport
40    java_import org.apache.thrift.transport.TTransportException
41    
42    tr = TSocket.new("10.0.0.151", 9160)
43    proto = TBinaryProtocol.new(tr)
44    client = Cassandra::Client.new(proto)
45    tr.open
46    
47    puts client.describe_cluster_name
48    puts client.describe_keyspaces
49    
50    timestamp = java.lang.System.currentTimeMillis()
51    path = ColumnPath.new("CrawlData")
52    path.setColumn(java.lang.String.new("url").getBytes("utf-8"))
53    
54    client.insert("Crawl", "abc", path, java.lang.String.new("http://google.com").getBytes("utf8"), timestamp, ConsistencyLevel::ONE)
55    
56    tr.close
57    
58    #cassandra> get Crawl.CrawlData['abc']
59    #=> (column=url, value=http://google.com, timestamp=1275509007789)
60    #Returned 1 results.
61    #cassandra> get Crawl.CrawlData['abc']['url']
62    #=> (column=url, value=http://google.com, timestamp=1275509007789)
63    #cassandra> get Crawl.CrawlData['abc']
64    #=> (column=url, value=http://google.com, timestamp=1275509007789)
65    #Returned 1 results.

Loading JARs into the Classpath

Dir.glob(Rails.root.join("java/*.jar")).each { |dir| $CLASSPATH << dir }

Rubinius

Exception Tree

  • Exception
    • NoMemoryError
    • ScriptError
      • LoadError
      • NotImplementedError
      • SyntaxError
    • SignalException
      • Interrupt
    • StandardError
      • ArgumentError
      • IOError
        • EOFError
      • IndexError
      • LocalJumpError
      • NameError
        • NoMethodError
      • RangeError
        • FloatDomainError
      • RegexpError
      • RuntimeError
      • SecurityError
      • SystemCallError
      • SystemStackError
      • ThreadError
      • TypeError
      • ZeroDivisionError
    • SystemExit
    • fatal

Add Dir to Load Path

$:.unshift File.dirname(__FILE__)

Class Methods

Calling a class method is a bit tricky especially when you have
inheritance involved. This is how to call said class method.

def inst_method
  self.class.class_method()
end

def self.class_method
  # Code
end

Typography

Scale

According to The Elements of Typographic Style the use of types should
be done using a scale. A scale makes the form of the type more
visually pleasing. There are also different proportions to use when
making the a scale.

Proportions
2 / 3
3 / 4
1 / Ψ
(defun typography-scale (scale current-num upto-num)
  (if (> current-num upto-num)
    '()
    (cons current-num (typography-scale scale (* scale current-num) upto-num))))

(mapcar 'fround (typography-scale (/ 1 3.14) 1 100))
  • Bootstrap CSS - At this point Bootstrap is the CSS scaffold of the
    web. It makes webpages look good enough and it makes it easy to
    built off it.
  • Subtle Patterns - Various background gradient overlays. Great for
    getting stuff off the ground.

DayOne / Jekyll Blog generator

So I wrote a DayOne blog generator for Jekyll. So I can write and publish things quickly. It will be fun to see how this will transpire in my writing. Or even if it will. But it was a cool little hack.

Last day at lookout. Been a fun ride.

X11 - XTerm Colors

I found this xterm schema to be quite nice. Put it in ~/.Xdefaults
file.

XTerm*background: #000000
XTerm*foreground: #9f9f9f
XTerm*color0: #000000
XTerm*color1: #9e1828
XTerm*color2: #aece92
XTerm*color3: #968a38
XTerm*color4: #414171
XTerm*color5: #963c59
XTerm*color6: #418179
XTerm*color7: #bebebe
XTerm*color8: #666666
XTerm*color9: #cf6171
XTerm*color10: #c5f779
XTerm*color11: #fff796
XTerm*color12: #4186be
XTerm*color13: #cf9ebe
XTerm*color14: #71bebe
XTerm*color15: #ffffff

Mutt

I am slowly moving to text based tools as opposed to using the web. I
will be making the configurations available for all the different
tools I decide to move to.

I decided that mutt was worth a try. So I put together a configuration
that works with Gmail by scouring the internet. First follow the
directions listed on Lifehacker’s article but use this for the
configuration. Change my email address to your’s at the appropriate
place.

Also, I want mutt to ask me for my password everytime I use it. This
is because… ARE YOU FUCKING CRAZY FOR STORING YOUR PASSWORD IN
CLEARTEXT?

When ever you delete from mutt what it does is removes the “label” so
stuff is never deleted but moved to “All mail”. So in this
configration there is no way to delete mail. If you want that please
look at the Lifehacker configuration.

# Change the following six lines to match your Gmail account details
set imap_user = "[email protected]"
# set imap_pass = "PASSWORD"

set smtp_url = "smtp://[email protected]@smtp.gmail.com:587/"
# set smtp_pass = "PASSWORD"

set realname = "Abhi Yerra"
set from = "[email protected]"

# Change the following line to a different editor you prefer.
set editor = "emacsclient"

# Basic config, you can leave this as is
set folder = "imaps://imap.gmail.com:993"
set spoolfile = "+INBOX"
set imap_check_subscribed
set hostname = gmail.com
set mail_check = 120
set timeout = 300
set imap_keepalive = 300
set postponed = "+[Gmail]/Drafts"
set record = "Sent"
set header_cache=~/.mutt/cache/headers
set message_cachedir=~/.mutt/cache/bodies
set certificate_file=~/.mutt/certificates
set move = no
set include
set sort = 'threads'
set sort_aux = 'reverse-last-date-received'
set auto_tag = yes
ignore "Authentication-Results:"
ignore "DomainKey-Signature:"
ignore "DKIM-Signature:"
hdr_order Date From To Cc
alternative_order text/plain text/html *
auto_view text/html
bind editor <Tab> complete-query
bind editor ^T complete

# Gmail-style keyboard shortcuts
macro index,pager gi "<change-folder>=INBOX<enter>" "Go to inbox"
macro index,pager ga "<change-folder>=[Gmail]/All Mail<enter>" "Go to all mail"
macro index,pager gs "<change-folder>=[Gmail]/Starred<enter>" "Go to starred messages"
macro index,pager tp "<change-folder>=[Gmail]/Important<enter>" "Go to priority inbox"
macro index,pager gd "<change-folder>=[Gmail]/Drafts<enter>" "Go to drafts"

# Spam stuff.
macro index,pager S "<save-message>=[Gmail]/Spam<enter>" "mark message as spam"
macro index,pager H "<save-message>=INBOX<enter>" "mark message as ham (not spam)"

Docker

Stop all containers

sudo docker ps -q | xargs sudo docker stop

Removing containers

sudo docker ps -a -q -notrunc | xargs sudo docker rm

Removing images

sudo docker images | grep ay-app | awk '{ print $3 }' | xargs sudo docker rmi

ffmpeg

ffmpeg -vcodec xvid -b 300 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec aac -ab 96 -i input_file.avi -s 320x240 -aspect 4:3 ipod_output.mpg

This creates videos that work fine with the iPod. I had some problems, though. Following command also works (thanks go here):

ffmpeg -i in.avi -f mp4 -vcodec mpeg4 -maxrate 1000 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec aac -ab 192 -s 320x240 -aspect 4:3 out.mp4

For 16:9:

ffmpeg -i in.avi -f mp4 -vcodec mpeg4 -maxrate 1000 -b 700 -qmin 3 -qmax 5 -bufsize 4096 -g 300 -acodec aac -ab 192 -s 320x180 -aspect 16:9 out.mp4

sed - Remove a line with a pattern

This is using the GNU version of sed. It replaces inplace anything
with payment_statement and the line after it.

gsed -i -e "/payment_statement/,+1 d" *

Adding Space to /tmp

sudo mount -o remount,size=40M tmpfs /tmp/

Adding Swap Space

The following creates a 4GB swap file. The count in dd is where you
specify this. So if you wanted to create 1GB it would be 1024 *

dd if=/dev/zero of=/swapfile1 bs=1024 count=4194304
mkswap /swapfile1
chown root:root /swapfile1
chmod 0600 /swapfile1
swapon /swapfile1

After you added the swap file you need to add it to /etc/fstab

vi /etc/fstab
/swapfile1 swap swap defaults 0 0

Restart the sound server

sudo kextunload /System/Library/Extensions/AppleHDA.kext
sudo kextload /System/Library/Extensions/AppleHDA.kext

sudo killall coreaudiod

Check the settings

select name, setting, boot_val, reset_val, unit
from pg_settings
order by name;

Vacuum Db

vacuumdb treely_production -e -v -f

Kill Hung Query

SELECT pid FROM pg_stat_activity;
SELECT pg_terminate_backend(<pid>);

Current Running Queries

SELECT * FROM pg_stat_activity;

User Notifications on Mac OS X

If you want to post a notification on Mac OS X’s Notification Center
this is the code that allows you to do it.

NSUserNotification *notification = [[NSUserNotification alloc] init];
[notification setTitle:@"Hello World"];
[notification setInformativeText:@"Hello world message"];
[[NSUserNotificationCenter defaultUserNotificationCenter] deliverNotification:notification];

Useful links to Android programming: CodePath Android Cliffnotes

Take Screenshots

Take a screenshot to a phone connected to the computer.

adb shell screencap -p | perl -pe 's/\x0D\x0A/\x0A/g' > screen2.png

Login to MySQL without root reds

If you want to login using without root credentials on MySQL:

1sudo mysql --default-file=/etcd/debian.d/defaults

Javascript Libraries

OAuth

Pieces

Resource Owner -> Client -> Server

A resource owner wants to give access to middle man to information he owns on
a remote server. The whole model is predicated on not giving the Client any
information on the user’s username/password. This also means taht the Resource
Owner can reoke Client’s access to Server’s resources by just going to the Server
and revoking it.

Credentials and Tokens

Consumer key and secret (client credentials). Used to authenticate the client with the server. This means that there is a unique key and secret that the server also keeps. This allows the server to validate what access to give the client and revoke access if need be.

This is how it is laid out for Servio as it relates to talking with Salesforce.:

kwai.oauths ez.ez_applications
consumer_key shared_key
consumer_secret secret_key (encrypted_secret_key)
callback  
  • access token and secret (token credentials) Used to validate user
    (resource owner) with server without giving up the user
    credentials (username/password) to the client.

    This means that the resource owner specifies on the server what
    permissions it is willing to give client. The server holds on to
    these permissions and allows the client to only act within the
    permissions that the user gives it.

    kwai.oauths ez_apps_user_accesses
    access_token request_shared_key
    access_secret secret_key (encrypted_secret_key)
      shared_key
  • request token and secret (temporary credentials)
    These are used to verify the user requests.

    This associates the user to a access. So instead of
    passing around an access token we pass a request which
    is more temporary and can be changed based on when access
    is dealt.

    kwai.oauths ez_apps_user_requests OAuth Teminology
    request_token request_shared_key oauth_token
    request_secret secret_key (encrypted_secret_key) oauth_verifier
      shared_key  

Request Urls

  • Temporary Credential Request
    https://photos.example.net/initiate

  • Resource Owner Authorization URI:
    https://photos.example.net/authorize

  • Token Request URI:
    https://photos.example.net/token