Wednesday, December 30, 2015

Multi-select (multi-cursor) functionality in the Atom Editor

If you've used Sublime Text, you may have become familiar with the neat multi-selection/multi-cursor functionality that you can use.  
Recently, I've started using the Atom Editor, and I wanted similar functionality to quickly select multiple lines of text and do the same action on all of them.
Apparently, there is some built-in multi-cursor functionality in Atom, but it's mouse-only.  You have to Ctrl-Click each place you want to put a cursor.
Luckily, Atom is extendable with open source packages, and I was able to find multi-cursor, which did almost everything I wanted.
The original directions for updating the keymap were incorrect, so it didn't function for me until I updated it to this.
'atom-workspace atom-text-editor:not([mini])':
  # Expand current cursor
  'ctrl-down': 'multi-cursor:expandDown'
  'ctrl-up':   'multi-cursor:expandUp'
Warning: Ctrl-Alt-(Up/Down/Left/Right) can be the default hotkeys of changing your screen's orientation in Windows, so unless you want to do that, update the atom keybinding to something else or remove those hotkeys from the graphics settings.
Luckily, this code is open-source, so I opened up a pull request on Github to fix the documentation to reflect how it worked for me.
The correct syntax for the keybinding you want to change in Atom can be obtained by going to "Settings" -> "Keybindings".

  • Search for the keybinding that you're having issues with (like ctrl-down), and click the clipboard icon next to the keystroke.
  • Paste that syntax into the keymap.cson file and edit as necessary.



Wednesday, August 5, 2015

Civic Hacking - Creating a Pebble Watch App for Recycling Data in Appleton, WI

TL;DR:  I released a Pebble App for Appleton Recycling Data.  It was fun.

Long Version:
Civic hacking is an activity that encourages people to take existing public data and mash it together or organize it in a clever way to increase its usefulness.  I've been intrigued by civic hacking ever since I saw the great work being done by Hacking Madison and CityCamp Madison, especially Greg Tracy's SMSMyBus project, and Scott Resnick's work towards creating Madison's Open Data initiative.

Recently, I had the honor of being invited to the Appleton's inaugural city hackathon.  It was held at Lawrence University on June 6, 2015.  When I was invited, I began to think about what I should do at the event.

Here were my guidelines.  I wanted something that was:
  • interesting, 
  • useful, 
  • and simple enough that I could expect to complete at least a small version of it if given a day to work on it.
Enter: Mike Putnam's Appleton API.

In his free time, Mike had created a way to interact with public data that was on Appleton's public portal, found at my.appleton.org.  I thought that given the work that Mike had already done, I could probably make a way for Mike's API to interface with a Pebble Watch, which I could use to check whether or not I needed to bring out the recycling.  I then challenged myself to complete a working version of the application by the end of the June 6th hackathon.

Here are the typical steps to code a working application from scratch:
  • Decide what you're going to code.
  • Determine what tools you need to write code.
  • Set up your "environment" and start coding.
  • Do a "hello world" app to start.
  • Modify the "hello world" app slightly.
  • Modify your "hello world" app to do your task at it's least complex level.
  • (Optional) Add complexity to get new features or make the app work better.
  • Ship it!
I'll describe these steps in relation to my Appleton Recycling Date Checker for the Pebble Watch
  • Decide what you're going to code.
I'm going to make a "Recycling Checker" for the city of Appleton, Wisconsin.  It will help me figure out when to put out the recycling bin, so that I don't forget.  It will be a Pebble watch application.
  • Determine what tools you need to write code.
To write Pebble applications, I first needed a Pebble developer account (which I had already created).  Next, you can either download and install their Pebble SDK (Software Development Kit) or make an application online in a web browser using CloudPebble.  I decided that because this app is for a hackathon,and it's a relatively simple app, I'd try out CloudPebble.  Using CloudPebble also meant that I could test my code on a "virtual" watch without having to load each change on a watch, which made coding go faster.

  • Set up your "environment" and start coding.

Since I was using CloudPebble, all I needed was a laptop, a web browser, and an internet connection.  If I wanted to install the application on an actual Pebble watch, I needed one of those, but I already had one, so I was good to go.  I decided to try using PebbleJS since it looked like a simplified, streamlined way of creating my application.  Creating a CloudPebble application does give you some sample code, and it allows you to get your feet wet without having to create your first project from scratch.
  • Do a "hello world" app to start.
After noodling around in the default CloudPebble app, I used the PebbleJS Tutorial to create my first project, since the tutorial allows you to edit the tutorial code directly.  I thought that was an awesome touch.  I went from zero to "hello world" very quickly because of this tutorial and its integration with CloudPebble.
  • Modify the "hello world" app slightly.
My first modification was to change the word "world" with "Appleton".  Changing one word without changing functionality is a safe first step in editing code.  That worked, so I continued on.
  • Modify your "hello world" app to do your task at it's least complex level.


The sample tutorial application gets weather information.  I wanted to get recycling information.  However, I could change the URL of the "weather" API call to Mike's "Appleton API" and try to get a meaningful result.  Luckily, one of the results the API returns is the next day that your recycling needs to be put out.  I hard coded my property ID (which represents my address) in order to test the web application call and display the data.

This is how the URL would look for the Appleton Makerspace:
http://3-1.appletonapi.appspot.com/property/315173204
It would return lots of data, including this:
[
    "generalinformation",
    {
        "2015leafcollectiondates": "October 19-23, November 2-6, November 16-20",
        "elementaryschool": "Lincoln",
        "firestationaddress": "1701 W. Brewster St",
        "firestationnumber": "5",
        "garbageday": "Monday",
        "highschool": "Appleton West",
        "middleschool": "Wilson",
        "recycleday": "Monday, 08-10-2015",
        "sanitarydistrict": "Appleton",
        "schooldistrict": "Appleton Area",
        "watersource": "Appleton" 
}, 

What I needed was hidden inside all of the other data.  I wanted to show the value for "general infomation"->"recycleday" on my screen.

Through some reading of the documentation, trial and error, and effort, I was able to accomplish this in 47 lines of Javascript:

var UI = require('ui');
var ajax = require('ajax');
var Vector2 = require('vector2');
// Show splash screen while waiting for data
var splashWindow = new UI.Window();
// Text element to inform user
var text = new UI.Text({
position: new Vector2(0, 0),
size: new Vector2(144, 168),
text:'Downloading trash data...',
font:'GOTHIC_28_BOLD',
color:'black',
textOverflow:'wrap',
textAlign:'center',
backgroundColor:'white'
});
// Add to splashWindow and show
splashWindow.add(text);
splashWindow.show();
// Make request to Appleton API
ajax(
{
//Proof of Concept - hard coded URL
url:'http://appletonapi.appspot.com/property/315427100',
type:'json'
},
function(data) {
// The location of the recycling day is data[1].recycleday;
var recycleDay = data[1].recycleday;
// Create a Card with title and subtitle
var card = new UI.Card({
title:'Next Recycle Day:',
subtitle:recycleDay
});
// Display the Card
card.show();
},
function(error) {
console.log('Download failed: ' + error);
}
);
  • (Optional) Add complexity to get new features or make the app work better.
I created a github repository with this code, so that I could easily track and change the application as I saw fit.  Most of the complexity came after the June 6th hackathon.  CloudPebble's integration with Github was very convenient here.
  • Ship it!
I downloaded the compiled"pbw" (pebble watch) file to my phone.  Using the Pebble App, I could download the Appleton Recycling App to my phone, and it would fetch recycling information for me.  Success was mine!

So..... now what?

I succeeded, but only at the smallest level.  The application still couldn't check more than one address, which wasn't configurable without creating your own application.  To make the application useful for anyone besides myself, I needed to implement a configuration page.  I researched how to do this (which was more complex than I would have expected - you have to host your own web page somewhere on the internet).

City Hackathon- the return!

Luckily, I was invited to a follow-up hack night, which was held at Appleton Coworking in July.  It gave me another opportunity to interact with other coders and civic minded folk, and I had another excuse to improve the app.  After discussing the event in the #dhmncivichacks channel at the Northeast Wisconsin Slack channel, I went in with the goal of improving the app so that other people could use it, too.  Thanks to some more trial, error, and tutorials (and some pizza purchased by Omni Resources), I succeeded in making a Github Pages-based configuration screen, which I hosted from my own github account.  The source code for that config trickery came from a fork of 
PebblePages (thanks, PaulBGD! - you can check out his blog here).

Ship it!  This time,  with feeling!


Given that another human being may actually find this application useful, I decided to publish the application in the Pebble appstore.  I needed to describe the application, make some screenshots, and make the application "production ready".  I decided to create a fork on the DHMN Civic Hacks Github Organization, and I published from there.  This means that I can make crazy changes to my local version without upsetting the "maybe more than one" user of this application!  Hooray!

So, you're done?
Nope.  I'm still working on the application.  Check out my Github Issues List if you're interested in where the future of this application may be.  Hurry!  It sounds like there will be another hackathon within the next month!


Monday, July 6, 2015

API Platform - Kevin Dunglas - creating an API centric application

For the francophones out there, here is a good talk about API-centric applications from Symfony Live using Symfony and API-Platform, a new framework to focus on apps around APIs.



If I have time on my hands, I'll try to translate this, but the guy talks fast, so there's a ton of text to translate.

Thursday, May 28, 2015

Google I/O 2015 - Watch it Live!

Google I/O tends to rock.  Check it out with the live widget below!  (note, this offer is time sensitive)

Monday, February 2, 2015

Upgrading a super old Docker install to update a Discourse forum.


Discourse-logo-big
I just had the fun process of upgrading a Discourse forum for my StartupWeekend company, Leagify.


The forum runs in a Docker container, of which my container is generously hosted by Netsonic in an Ubuntu 14.04 virtual machine.
Netsonic Logo

Typically, upgrading Discourse is super easy.  There is a docker admin page that allows you to update directly from the web interface.  However, I had an ancient version of docker from my original installation, and it needed to updated, which could only be done from the command line.

The command line steps are outlined here:
cd /var/discourse
git pull
./launcher rebuild app

However, these steps didn't work for me, and I got a couple of different error messages.  One of them said something like "Your docker installation is old, please upgrade to 1.2" presumably because my install was really old, and my forum doesn't apparently follow the (now) standard guidelines for installing.

This article describes how I got the upgrade to work for my installation, since I haven't seen a good description of the steps I used all in one place.
  • SSH into your box  If you're reading this, I hope you can handle this step.
  • Don't just install docker from apt-get!  The 14.04 repo versions are OLD!  Also, note the difference between docker and docker.io, as they are different!  You probably want docker.io for a reasonably up-to-date docker install, but even this was too old for my purposes.
  • Re-Install Docker using Docker's instructions.  I opted for the easy curl script: 
curl -sSL https://get.docker.com/ubuntu/ | sudo sh
  • If you were an early adopter of Discourse, you may have put your container in /var/docker instead of /var/discourse.  This is a problem, but not as big of a problem as you'd think.  Do a recursive copy of /var/docker to /var/discourse: 
sudo cp -a /var/docker/ /var/discourse/

  • You should be able to run the rest of the Discourse update steps as originally planned.  You may need to use sudo for some of these commands, depending on how your permissions are set up.
cd /var/discourse
git pull
./launcher rebuild app

  • If these steps don't work, try rebooting the server and doing the official steps one more time.


Hopefully, your wonderful Discourse forum is now up and running again after the 15-20 minutes it took to perform all of these steps! If not, check out the Discourse forums for more information and troubleshooting tips!

New Quad Core Raspberry Pi 2 - a 35 dollar Windows 10 machine?

The Raspberry Pi 2 was announced today.  Sweet.

For me, the biggest surprise wasn't that a quad core ARM machine could be made for 35 dollars.  The Odroid C1 beat them to that punch.

The biggest surprise to me is that is has baked in Windows 10 support, and licenses are available to makers free of charge.  Microsoft is making some good moves in the tech space to help them earn back the trust of makers who were long scorned by Microsoft's previous policies that were not friendly to the hacker on a budget.  Will it work?  Time will tell.  You can't blame Microsoft for extending the olive branch.  Well, you can, but it just isn't that productive.