Tuesday, 28 January 2014

Archively: Delayed Archive/Delete in Gmail

Ever wanted some emails to go away on their own? It might be an "I'm away for two weeks" email, and you don't want to delete the email right now or you'll forget that they're not contactable. Or do you get emails like "Fridge is being cleaned this Friday"? Well, now you can set them to be deleted or archived (or both!) when you want them to be. Enter Archively, a Google Apps Script written in JavaScript.

What Archively does is scan for labels that instruct it to archive and/or delete emails. There are two top level labels, namely, "delete" and "arkive" (the label "archive" is reserved by Gmail). To archive, the label should be nested under "arkive", with a name like "in 5 days". To the Google Apps Script, the label will look like "arkive/in 5 days". Here are some examples of labels that are understood by Archively:
  • arkive/at EOD this will archive the message/thread just after midnight (at End Of Day).
  • arkive/at EOD+1d this will archive the message/thread after midnight the following day (at End Of Day plus one more day).
  • arkive/when 7wks old will archive the message/thread when the last message in the thread is 7 weeks old. If any new messages arrive (in this thread), it will have to wait till the latest message is 7 weeks old.
  • delete/in 2 weeks will delete the message/thread two weeks after the label is spotted.
  • delete/on 3 Feb 2014 will delete the message/thread at 12 AM (00:00) on the specified date.
  • delete/on 3 Feb 2014 9:00 will delete the message/thread within an hour after the specified time (I recommend that the script only runs once an hour).
  • There are a few more examples listed at the top of the source code.

One of the main ways I am using Archively for is via a filter. One of the filters I have picks out marketing style emails with a specific keyword in it, and then labels the email with delete/at EOD+2d. To get Archively working for you, follow these easy steps:
  1. Copy the text out of my copy of the script here or here.
  2. Go to Google Drive and create a new Script. If you don't see a "Script" option, you'll need to choose "Connect more apps" and then pick Google Apps Script (also says "Script in Google Drive").
  3. In the new Script, paste in the text that was copied in step 1.
  4. Do a test run if you want: Select the checkEmAll function and run it.
  5. Select menu Resources > Current project's triggers. Add a trigger to run checkEmAll hourly, and cleanDbRecords weekly (or some other frequencies as desired).
  6. At some point you'll need to authorise the script to work with your Gmail account.
  7. From within Gmail, create the base labels delete and arkive. Then you will easily be able to create labels nested under them.
  8. Now you can apply labels directly, or set up filters to apply Archively labels for you.
For those of you that are interested, here is an approximate description of the grammar of the labels understood by Archively in Extended Backus-Naur Form. Note that it is not case-sensitive.
LabelText = "delete/" | "arkive/", TimeSpec;
TimeSpec = EndOfSpec | AgeSpec | WhenSpec | FromNowSpec;

EndOfSpec = "TOMORROW"
          | (["AT", {" "}], "EO", "D"|"W"|"M"|"Y"|"FY", {
    Tomorrow is an alias for EOD. The end of day (D), week (W), month (M), year (Y) and financial year (FY) are available. A month is defined as 31 days.
AgeSpec = ["WHEN "], {TimeSpan}, " OLD";
WhenSpec = "ON ", JavaScriptDate;
    The description of JavaScriptDate is left to the Internet. DateTimes such as "14 Jan 2014", and
"14 Jan 2014 11:00" should work just fine.FromNowSpec = ["IN "], {TimeSpan};TimeSpan ={" "}, ["-"|"+"], {" "}, Number, {" "}, TimeUnit;
TimeUnit =
("H", ["R" | "RS" | "OUR" | "OURS"])
("D", ["AY" | "AYS"])
["K" | "KS" | "EEK" | "EEKS"])
         | ("M", ["ONTH" | "ONTHS"])

         | ("Y",
["R" | "RS" | "EAR" | "EARS"]);
Number = (Digit, {Digit}, [".", {Digit}])
       | (".", Digit, {Digit});
Digit = "0"|"1"|"2"|"3"|"4"|"5"|"6"|"7"|"8"|"9";
Get the the script here or here. Enjoy!
Creative Commons License
Archively by Jonathan Johansen is licensed under a Creative Commons Attribution 4.0 International License.

Monday, 30 December 2013

Window Snapper

Many programs have a nice dividers in their GUI - and you can usually drag the divider to resize the panels on either side. I've often been a little frustrated when resizing windows to tile them to fill the screen. Perhaps a Word document on the left, a PDF in the upper right, and email in the lower right. It was quite tedious, and because of that I didn't do it often, and I feel this slightly diminished the power of windows. So I wrote an AutoHotkey script and now I have what I wanted.

To use it, while the script is running, you can right-button drag window borders, and the script will move all neighbouring window edges at the same time. The script will grab window borders within 10 pixels (configurable) of the border/s you are right-button dragging. It also assumes a seven pixel wide window resize border, but that's also configurable at the top of the script. You can resize from edges or corners - giving you lots of power when resizing windows.

The most common use-case I have is with just two windows positioned with Win+Left and Win+Right (like explained here). With this script you can resize both windows effortlessly.

Here's an example of it in action:
 I can resize all five windows with one right-button drag, in the area where the four window corners meet in the middle of the screen. If I drag towards the upper right, I can get something like this:
 And things like this are possible too, but unsnapping window edges like I've done below with the left and right can be a little fiddly. I could potentially add something like Ctrl+Right-Click to only resize windows actually near the mouse...
Please have a go with the window snapper script. Please let me know what you think after using it!

Creative Commons License

Friday, 19 July 2013

Engagement in the Family

My brother-in-law Rowan Barton is engaged to Elpida Savvidou. This is awesome news (even if not recent :-). Their engagement party is movie themed, and we've got some western style props, so I've created custom wanted posters! Here they are:

A wanted poster showing that Elpida is wanted alive for stealing a heart, reward $1000.

A wanted poster showing that Rowan is wanted dead or alive for parental bank robbery, reward $1000.

Once printed we are going to brown the edges with the heat from a fire.

The SVG files were created with Inkscape (Trace Bitmap is fantastic) and are available for use if you'd like. I put them in the public domain (but I'd be thrilled to hear from you if you use these). They make use of the Playbill font.

I'm interested to see what other people have created. Enjoy :-)

Saturday, 13 July 2013

Minecraft vs Real Life

I have been digging a hole in the ground. It is just a bit more than one and a half metres deep, and around a metre in diameter. Here is the hole:

A hole in the ground about 1 metre in diameter and just over one and a half metres deep.

Here is the hole with the dirt I have emptied out of the hole in view:

The same hole as in the previous picture but showing the piles of 'hole' dirt around it.

Here is an equivalent sized hole in Minecraft:

Apart from the Minecraft hole being digital, it was also a lot neater. And it took less time to dig. The real hole above has taken several weekends of digging - probably close to 20 hours of digging. The Minecraft hole took around 20 seconds, that's including deciding where to dig. Perhaps that's one reason why games like Minecraft are enjoyable to play - they let you do mundane things really quickly.

Saturday, 6 July 2013

Bits of Minecraft

Minecraft has sunk a lot of my time over the few years it's been around. Here are some of the things I've done in it (in order of construction):

A rainbow made of wool is visible to the left, and a large woolen cake lurks in the fog to the right.
Rainbow! ... and cake

A triple helix with hanging vines made of dirt rises into the sky in front of a seemingly floating land.
Triple helix near an overworld plate

From my overworld you can see my home base tower on the left, satellite dish in the centre and the word "Craft" made of wool on the right.
Home, satellite dish and "Craft"
The rainbow, triple helix and satellite dish were all planned using Lisp. Here's some Lisp code you can use to plan rainbows:

(loop with freq = (list)
       and reach = (1+ 20)
       and width = 8
      for j from reach downto 0
    do (loop for i from (- reach) to reach
             for r = (round (sqrt (+ (square i) (square j))))
             for c = (cond ((= i j 0) #\+)
                           ((< r (- reach width)) #\-)
                           ((<= r (1- reach)) (- r (- reach width)))
                           (t #\Space))

        when (not (eql #\Space c))
        do (aif (cdr (assoc c freq))
            (incf (car it))
            (push (list c 1) freq))
        when (or (minusp i) (not (eql #\Space c))) do (princ c))

    do (terpri)
    finally (return freq))

It produces output like this (this one's a small version to fit in the width of the blog):

((#\+ 1) (#\- 256) (0 45) (1 45) (2 43) (3 57) (4 57) (5 57) (6 59) (7 57))

The last bit is a count of each block type so you know how much to gather of each type. Three dimensional objects like the dish and triple helix use more code which I can post if people are interested.

P.S. Don't spend too much time playing computer games.