Tuesday, October 22, 2013

Search bash history in shell-mode (emacs)

Here's a quick elisp to grab the bash history content and insert it in a shell buffer (or anywhere). Kind of like CTRL-R in bash but better because you get ido interface.

(insert (ido-completing-read
             "History: "
             (sort
              (delete-dups
               (split-string
                (with-temp-buffer
                  (insert-file-contents "~/.bash_history")
                  (buffer-string))
                "\n"))
              'string<))))

Friday, April 12, 2013

Delay the HTTP response of static contents

When you are developing a site on a local machine, contents from
localhost load super fast. Moving your site online may reveal
unexpected delays. For example, you have a page with a bunch of
rotating images. How will you page react if an image takes 10 seconds
to load? Are you going to have a blank area for 10 seconds?

Here's a small nginx trick to add a delay (sleep) to a resource:

location /subrequest { 
  alias /srv/www/static/cat.jpg; 
} 

location /static/cat.jpg { 
  echo_sleep 3.0; 
  echo_location /subrequest; 
}

Tuesday, October 2, 2012

Script to extract email attachments from mbox / Thunderbird

Here's a Python script that extracts file attachments from emails
stored in an mbox file. Mbox is the format used by Thunderbird and
plenty other mail clients. That script can be used to automatically
save email file attachments to a specific folder. Using the content
type you can customize what's get downloaded/saved and where files are
saved. A setting file saves the state of which messages have been
saved.
import mailbox, pickle
mb = mailbox.mbox('/path/to/INBOX')

prefs_path = '/path/to/config/.save-attachments'
save_to = '/path/to/Downloads/attachments/'

try:
    with open(prefs_path, 'rb') as f:
        prefs = pickle.load(f)
except:
    prefs = dict(start=0)

def save_attachments(mid):
    msg = mb.get_message(mid)
    if msg.is_multipart():
        for part in msg.get_payload():
            if part.get_content_type() != 'application/octet-stream':
                continue
            notify('Saving' % part.get_filename())
            with open(save_to + part.get_filename(), 'wb') as f:
                f.write(part.get_payload(decode=True))

for i in range(prefs['start'], 1000000):
    try:
        save_attachments(i)
    except KeyError:
        break
prefs['start'] = i

with open(prefs_path, 'wb') as f:
    pickle.dump(prefs, f)

Saturday, September 10, 2011

Hacking the Python syntax (implicit return values)

Python provide some functional programming features. However, the return value of a function has to be explicit. You have to use the keyword return in order to tell the function to return a value. Else, the function will return None. In some languages, the last value of a function is the return value. I like this behavior and I would like to have that in Python too. It turns out, that it's possible to modify the language by hacking the code AST (abstract syntaxe tree). The code below transforms the last expression of a function into a return.
from compiler.ast import *
import compiler, inspect

def modify(f, alter):
    "Modify function f using alter and make the new function available"
    # get code and modify
    raw = compiler.parse(inspect.getsource(f))
    raw.node.nodes[0].getChildren()[5].nodes = alter(raw.node.nodes[0].getChildren()[5].nodes)
    # generate
    compiler.misc.set_filename("temp", raw)
    expr = compiler.pycodegen.ExpressionCodeGenerator(raw).getCode()
    eval(expr, f.func_globals)

def hack(nodes):
    "Transform the last node of the AST into a return"
    newnodes = []
    for node in nodes:
        newnodes += [node]
    last = newnodes[-1]
    if "Discard" in str(last):
        newnodes[-1] = Return(last.getChildren()[0])
    return newnodes

def square(x):
    x*x

modify(square, hack)
print square(3)

Sunday, April 10, 2011

Lisp interpreter in javascript with jQuery

I started using lisp a few years ago when I wanted to configure the hell out of emacs. After understanding lisp better thanks to some great videos,I built my own lisp interpreter. After two days of work, I had a somewhat working system. The interpreter is not complete however it runs some basic expressions. I guess the code is interesting for CS students trying to understand lisp better. There aren't much comments in the source code but the logic is split into small functions. It shouldn't be too difficult to read. First the lisp string is turned into a list that is passed to the eval-apply cycle and voila.

You can get the source code and add issues on the Google Code page.

Examples of what you can evaluate

Factorial

(defun fact (x) (if (<= x 1) 1 (* x (fact (- x 1)))))
(fact 5)

Reverse a list

(defun reverse- (x r)
(if (not (car x)) r (reverse- (cdr x) (cons (car x) r))))
(defun reverse (x) (reverse- x (list)))
(reverse (list 1 2 3 4))

Map a list

(defun mapcar (x f)
(if (not (car x)) (list) (cons (f (car x)) (mapcar (cdr x) f))))
(mapcar (list 1 2 3) (lambda (x) (* x x)))

Here's what you can use


car cdr cons
not and or
>= > <= < = eq
+ - * /
nil list setq if lambda defun
There's also a js function. It's to call any javascript function. Try ((js Math.abs) -23)

More javascript lisp interpreters

Some people have written this kind of program before. I have tried them but I couldn't evaluate expressions the way I wanted. You can take a look at the work of Paul M. ParksJoe Ganley or Brian Morearty.


Tuesday, March 1, 2011

Build a chart from Org-mode clocks

Org-mode is a great todo and agenda application. It's possible to use it to clock how much time you spend on a task. I've been clocking my work for a few months using org-mode. I love that I can get a summary of how much time I have spent on each stuff I do. However, it's difficult to see how much time you spend daily. You have to look at each clock entry and sum the durations. Not very friendly. My idea was to chart the hours spent per day. You put the cursor on any task and you get a bar chart showing you how much time was spent per day.

It's turning this:

*** project1
**** task1
     CLOCK: [2010-11-20 Sun 19:42]--[2010-11-20 Sun 20:14] =>  0:32
     CLOCK: [2010-11-20 Sun 18:54]--[2010-11-20 Sun 19:24] =>  0:30
     CLOCK: [2010-11-20 Sun 17:25]--[2010-11-20 Sun 17:40] =>  0:15
     CLOCK: [2010-11-20 Sun 15:07]--[2010-11-20 Sun 15:45] =>  0:38
     CLOCK: [2010-11-20 Sun 10:06]--[2010-11-20 Sun 12:37] =>  2:31
     CLOCK: [2010-11-19 Sat 17:21]--[2010-11-19 Sat 19:33] =>  2:12
     CLOCK: [2010-11-19 Sat 14:52]--[2010-11-19 Sat 16:53] =>  2:01
     CLOCK: [2010-11-18 Fri 17:45]--[2010-11-18 Fri 18:27] =>  0:42
     CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 15:20] =>  4:03
**** task2
    :LOGBOOK:
    CLOCK: [2010-11-19 Sat 12:51]--[2010-11-19 Sat 14:52] =>  2:01
    CLOCK: [2010-11-18 Fri 17:08]--[2010-11-18 Fri 17:45] =>  0:37
    CLOCK: [2010-11-18 Fri 11:17]--[2010-11-18 Fri 11:17] =>  0:00
    CLOCK: [2010-11-17 Thu 12:40]--[2010-11-17 Thu 13:05] =>  0:25
    CLOCK: [2010-11-17 Thu 10:16]--[2010-11-17 Thu 11:58] =>  1:42
    CLOCK: [2010-11-16 Wed 19:32]--[2010-11-16 Wed 20:29] =>  0:57
    CLOCK: [2010-11-16 Wed 14:06]--[2010-11-16 Wed 16:04] =>  1:58
    CLOCK: [2010-11-16 Wed 11:55]--[2010-11-16 Wed 13:00] =>  1:05
    CLOCK: [2010-11-15 Tue 16:32]--[2010-11-15 Tue 17:59] =>  1:27
    CLOCK: [2010-11-15 Tue 10:55]--[2010-11-15 Tue 12:27] =>  1:32
    CLOCK: [2010-11-14 Mon 18:05]--[2010-11-14 Mon 19:52] =>  1:47
    CLOCK: [2010-11-14 Mon 16:10]--[2010-11-14 Mon 17:46] =>  1:36
    CLOCK: [2010-11-14 Mon 14:40]--[2010-11-14 Mon 15:24] =>  0:44
    CLOCK: [2010-11-14 Mon 09:50]--[2010-11-14 Mon 11:34] =>  1:44
    CLOCK: [2010-11-13 Sun 22:22]--[2010-11-13 Sun 23:17] =>  0:55
    CLOCK: [2010-11-13 Sun 15:23]--[2010-11-13 Sun 18:56] =>  3:33
    CLOCK: [2010-11-12 Sat 14:25]--[2010-11-12 Sat 17:08] =>  2:43
    CLOCK: [2010-11-11 Fri 19:25]--[2010-11-11 Fri 19:52] =>  0:27
    CLOCK: [2010-11-11 Fri 15:30]--[2010-11-11 Fri 18:15] =>  2:45
    CLOCK: [2010-11-11 Fri 10:26]--[2010-11-11 Fri 12:26] =>  2:00
    CLOCK: [2010-11-10 Thu 15:12]--[2010-11-10 Thu 18:49] =>  3:37
    CLOCK: [2010-11-10 Thu 10:08]--[2010-11-10 Thu 12:42] =>  2:34
    CLOCK: [2010-11-09 Wed 22:18]--[2010-11-10 Thu 00:13] =>  1:55
    CLOCK: [2010-11-09 Wed 15:09]--[2010-11-09 Wed 15:59] =>  0:50
    CLOCK: [2010-11-09 Wed 14:05]--[2010-11-09 Wed 14:50] =>  0:45
    :END:

Into this:
chart?chxl=1:|09|10|11|12|13|14|15|16|17|18|19|20|21&chxr=0%2c0%2c8|1%2c0%2c105&chxt=y%2cx&chbh=15&chs=600x400&cht=bvg&chco=80C65A&chds=0%2c8&chd=t:3.283333333333333%2c6.4%2c5.2%2c2.716666666666667%2c4.466666666666667%2c5.85%2c2.9833333333333334%2c4.0%2c2.1166666666666667%2c5.366666666666666%2c6.233333333333333%2c4.433333333333334%2c0.0&chg=0%2c25%2c0%2c0&chma=|5%2c10&chtt=Clocked+Activity+%2812+days%2c+53+hours%29&chm=h%2cFF0000%2c0%2c0.552604%2c1
Behind the scene, I've used Google chart api, and a few lines of emacs lisp. If you like that, copy the code below in your .emacs and bind a key to org-chart-clocks-current-item

(define-key org-mode-map [f4] 'org-chart-clocks-current-item).

If you change the code, I'll love to hear about your hacks. So, let me know. The most recent version of this code lives somewhere in this file: http://code.google.com/p/marcshacks/source/browse/elisp/personal/marcshacks.el