Selecting columns in Sublime Text turning your screen upside down?

The way to select a column in Sublime Text on Windows is by using + and then pressing the up or down arrow keys. You might get a surprise though if you try it in the form of you entire screen display flipping upside down. Some people don’t even know this is possible to do so they get extra surprised.

This is because on certain Intel graphic cards, there are the hotkeys to trigger certain functions of the graphic card, for example being the functions to flip and rotate the screen (this is handy for instance if you want to work with your screen physically rotated to be in portrait rather than landscape mode and you’d obviously want to render the desktop accordingly). The keys to select a text column in Sublime Text happens to be taken by the hotkey for flipping the screen by the graphic card.

To disable this key combination being hijacked by the graphic card, you can either customize the graphic card to use a different key combination (Ctrl+Alt+F12 > Options) or disable the hotkeys for graphic functions altogether (Ctrl+Alt+F12 > Options > Uncheck “Enable Hot Keys”)

Found the above thanks to a comment here (by L_7337)

Importing an .ics file to Google calendar

Someone sent you an invitation to an event as an .ics file, and you wish to add it to your Google calendar

The first part is to import the file. To do this, click the + icon to the right of the “Add a friends calendar” located on the left side of the page. After clicking the icon, from the available options select ‘Import’

Now, the obvious thing to do would be to just to click the button that says “Select file from your computer”, select the .ics file and click import, but if you would do that, chances are that you’ll see the dreaded:

‘Failed to import events: Could not upload your events because you do not have sufficient access on the target calendar..’

The solution for this is to manually edit the .ics file prior to importing it and replace all occurrences of “UID:” with “UID:X” (without the quotes). After doing this and saving the file, proceed with the import and all should be fine.

Learned this from here

Notepad tricks in Google Docs

Many people are not aware that since the early days of the simple notepad app that comes bundled with Windows, it had the following undocumented feature: If you enter the text .LOG as the first line of the file, then every time you open the file with notepad, it will append the current date and time to the end of the document and scroll there. This is quite handy when you want a file that keeps track of the time when you added new entries.

I wanted to have the same functionality with Google Docs (with the added benefit of not needing to write .LOG at the beginning of the file). The following script (built via multiple shameless plagiarism from various sources) enables that functionality:

function onOpen() {
  var ui = DocumentApp.getUi();
  // Or FormApp or SpreadsheetApp.
  ui.createMenu('Custom Menu')
      .addItem('Insert Date', 'insertDate')
      .addToUi();

  setCursorToEnd()
  insertDate();
  setCursorToEnd()
}

function setCursorToEnd()
{
  var doc = DocumentApp.getActiveDocument();
  var paragraph = doc.getBody().appendParagraph('');
  var position = doc.newPosition(paragraph, 0);
  doc.setCursor(position);
}

function formatDate()
{
  var date = new Date();
  var datestr = date.getFullYear() + '-'+  
    ('0' + (date.getMonth()+1)).slice(-2) + '-' + 
    ('0' + date.getDate()).slice(-2);  
  var hours = date.getHours();
  var minutes = date.getMinutes();
  var ampm = hours >= 12 ? 'pm' : 'am';
  hours = hours % 12;
  hours = hours ? hours : 12; // the hour '0' should be '12'
  minutes = minutes < 10 ? '0'+minutes : minutes;
  var strTime = hours + ':' + minutes + ' ' + ampm;
  return datestr + "  " + strTime;
}

function insertDate()
{
  var activeDoc = DocumentApp.getActiveDocument();
  var cursor = activeDoc.getCursor();
  if (cursor) {
      var date = formatDate();    
      var element = cursor.insertText(date);
  } else {
      DocumentApp.getUi().alert('Cannot find a cursor in the document.');
  }
}

To enable this for a document, In Google Docs : Tools -> Script Editor, enter and save the above script and then accept the permissions.

Status of specific brew service

Switching between various development environments, to save restart time, I wanted to start various services from OS/X only if they were not already running. Brew does not have a method to know whether a particular service is running (AFAIK), so the following example code parses the list of services returned by brew services list and then enables quickly checking the status of a given service and acting accordingly:

#!/bin/bash
brew services list | awk -F " " '{print $1 "=\"" $2 "\""}' > __tmp__.sh
chmod u+x __tmp__.sh
source ./__tmp__.sh # so that variables are maintained in this shell
rm ./__tmp__.sh

if [ "$php72" == "started" ]; then
        echo "PHP service is up"
fi

if [ "$openresty" == "started" ]; then
        echo "Openresty service is up"
fi

PHP – switch statement vs. function dispatching

When you start having too many cases in your switch statement, it might be worth looking into using a function lookup. This is possible in all languages where functions are first class citizens…

<?php
$post = "hello";
$info = "3.1415";
//-----------------------------------------------------------
// Version 1 - using a switch statement
//-----------------------------------------------------------

switch ($post) {
    case "hey": {
        print("I've been called with $info\n");
        break;
    }

    case "there": {
        print("I've been called with $info\n");
        break;
    }

    case "hello": {
        print("I've been called with $info\n");
        break;
    }

    default: {
        print("shouldn't have gotten here\n");
    }
}

//-----------------------------------------------------------
// version 2 - same thing using a dictionary of functions
//-----------------------------------------------------------

$funcArray = Array(
    "hey" => function ($param) {
        print("I've been called with $param\n");
    },
    "there" => function ($param) {
        print("I've been called with $param\n");
    },
    "hello" => function ($param) {
        print("I've been called with $param\n");
    }
);

// The data driven invocation of the correct function:

if (isset($funcArray[$post])) {
    // Invoke the relevant function if the string is found
    $funcArray[$post]($info);
}
else {
    print("shouldn't have gotten here\n");
}
?>

Virtual Box – Shared folders on Ubuntu Guest

Well, the first thing to make sure is that Guest Additions are correctly installed. For example, on Ubuntu 16.04 guest on VirtualBox 5.0.32 r112930 I received a message that the kernel headers were not found (even though they did exist). This was fixed with:
sudo apt-get install dkms

Next problem was constantly receiving a protocol error when trying to mount the host’s directory that I named hostfs in the VirtualBox shared folders dialog. This however, was my fault – the correct syntax to do this is:

sudo mount -t vboxsf -o uid=1000,gid=1000 <name-given-in-virtualbox-dialog> <empty-directory-path-in-guest>

Creating an iOS push certificate PEM file

in the Apple developer console:

  • Create a development iOS certificate of type “APNs Development iOS” – this is a certificate used to connect between your entity that sends the push (e.g a php script on a server or some other app) and the APN development (sandbox) gateway that delivers the push to the remove iOS device.

Creating a APMs push certificate is done by following the steps in adding a certificate in the development console, which includes selecting the certificate type, selecting the App ID it should be associated with (e.g. com.naturongo.mypush) downloading the certificate request, double-clicking the request file and using the KeyChain Access application to fill out the request, uploading the resulting file and the signed certificate will be generated.

  • Click the download button for this certificate – this will download a .cer file to your local drive

  • Double click this .cer file – this should add it to your keychain via the Keychain Access application

  • Once you’ve identified it in your Keychain Access application, ctrl-click it and select the export option.

  • Export it to a .p12 file. You will be requested for a password to be used for accessing the private key in this file – lets suppose the password is “pass”

  • Once you have the .p12 file on your drive – lets call it cert_push_dev.p12 then convert it to a pem file via:
    openssl pkcs12 -in APN_push_dev.p12 -out APN_push_dev.pem -nodes -clcerts

  • The assumption is that at this point you have the following:
  1. An APN token from an iOS application that registered with an APN Server
  2. The pem file created in the previous step
  3. The password to this pem file

    Given all this, you can now use the following php script to send a push notification to the remote iOS device associated with the APN token:

    <?php
    
    // This is the APN token received by the iOS device when registering with the APN server
    $deviceToken = "aba3213b06b13d33b881058bfe8c88478a1d1d07fbed6d3303afc904fe874e7d";
    
    $message = 'You have recieved new notification!';
    
    $ctx = stream_context_create();
    stream_context_set_option($ctx, 'ssl', 'local_cert', 'APN_push_dev.pem');
    stream_context_set_option($ctx, 'ssl', 'passphrase', 'pass');
    
    // Open a connection to the APNS server
    //$APNS = 'ssl://gateway.push.apple.com:2195'; // production server
    $APNS = 'ssl://gateway.sandbox.push.apple.com:2195'; // development
    $fp = stream_socket_client( $APNS, $err, $errstr, 60,
                                STREAM_CLIENT_CONNECT|STREAM_CLIENT_PERSISTENT, $ctx);
    
    if (!$fp) {
        exit("Failed to connect: $err $errstr" . PHP_EOL);
    }
    
    echo 'Connected to APNS' . PHP_EOL;
    
    // Create the payload body
    $body['aps'] = array(
        'alert' => $message,
        'sound' => 'default',
        'data' => 'test data'
    );
    
    // Encode the payload as JSON
    $payload = json_encode($body);
    
    // Build the binary notification
    $msg = chr(0) . pack('n', 32) . pack('H*', $deviceToken) . pack('n', strlen($payload)) . $payload;
    
    // Send it to the server
    $result = fwrite($fp, $msg, strlen($msg));
    //echo "send result=$resultn";
    if (!$result) {
        echo 'Message not delivered' . PHP_EOL;
    }
    else {
        echo 'Message successfully delivered' . PHP_EOL;
    }
    
    // Close the connection to the server
    fclose($fp);
    ?>

If the above file is named push_ios.php then
Sending a push notification can now be done by running php from the command line:
php -f push_ios.php