fredagen den 28:e september 2012

New project: HappyEdit


When I first started programming, I was using IDEs such as Eclipse and Visual Studio. After a few years, I switched to Vim because I wanted something faster and lighter with less clutter in the UI. Vim is just about as clutter-free and fast to work with as an editor gets, so I've been quite happy with it. But I've started to miss features from other editors such as being able to jump to definitions, CommandT, autocompletions and lint warnings. I know many of these things can be achieved with plugins but Vim's plugin system is a mess and as soon as something requires a tiny bit of UI, the terminal is not very good for it.

So what about MacVim, GNOME-Vim, KVim, etc? These editors really only shove terminal-Vim inside an app window, and that doesn't solve any of the issues pointed out.

Ok, but what about the IDEs with a Vi-mode that can be turned on, like Komodo, Cloud9 or even Eclipse with any of its Vi plugins? These all have the kind of UI that made me switch to Vim in the first place, and the Vi-mode tends to be treated as a second class citizen.

Vi and Vim have a very different way of doing things. This is not only apparent their keybindings, but affects UI and other elements as well. I think that if you want to build an editor for Vi-users, you have to focus on the Vi of doing things, so you basically have to choose, do I want to make a Vi-like editor or a more standard one.

There's really only one editor that have made a real attempt at pushing Vi-like editors forward, and that's Vico. I like Vico very much, it has some awesome ideas and design, but its UI is focused on sidebars like traditional IDEs, and it hasn't done anything special with the command line which for me is the most important part of a Vi-like editor. It's also a Mac OS X application, and as the world is being taken over by smartphones, tablets and Chromebooks, the desktop platform is a dead end and the web is the way forward. In the future, I want to be able to pick up any iPad or Firefox Phone (FirePhone?) and start coding without entering a development mode or jailbreaking my device.

So I've started work on a new editor that I call HappyEdit. Basically it takes the soul of Vim: the commands, keybindings, the concept of different modes, the fast editing and clutter-free interface, and adds modern features common in other editors. All using modern web technologies.



I've been working full time on this project for two weeks now and I have to say that the result is mighty pleasing. The alpha version I've got running feels very nice to use and has already replaced MacVim as my main editor. But I need more time to work on this, so I've started a fund raising campaign over at Indiegogo where you can support this project and get cool stuff in return.


Features already implemented:

  • Vim like INSERT/COMMAND/NORMAL modes, keybindings and search.
  • Beautiful command line with autocompletions for files and commands.
  • Tabbed interface.
  • Minimalistic window border design.
  • Blazingly fast syntax highlighting for 40+ languages.
  • CommandT-like way of opening files.
  • A remote mode so that you can work on files that are on another computer.


Upcoming features:

  • A better way of searching multiple files, replacing vimgrep.
  • A settings panel exposing options that are hard to find in Vim.
  • Window splits.
  • Ability to drag tabs between windows.
  • Jump to definition & symbol navigation.
  • Plugin system.


Open Source, Chrome Web Store and the Mozilla Marketplace
In order to get a separate app window, desktop icon, file system access, etc, HappyEdit uses upcoming APIs from Chrome and Mozilla. Even though I plan on selling HappyEdit through these channels, the source code for HappyEdit is 100 % open source and can be found at GitHub.

HappyEdit is based on the Ace editor being worked on by Cloud9 with roots from Mozilla's Bespin project, and I push as much work as possible upstream to Ace.

The future of this project
With v1 of HappyEdit, I aim for a stable release that any Vim user will feel comfortable picking up and start using. I aim this release for when Mozilla Marketplace or the Chrome Web Store launches and finalizes their APIs.

After v1, my plan is to start on the plugin system. But making a great plugin system is not easy to pull of: it should be flexible enough so that many different ideas can be implemented, at the same time it should place restrictions so that plugins don't conflict with eachother and developers have a clearly laid out path to follow. There is quite a bit of research, thinking and discussion that needs to take place before work on this begins.

Links:
Official home page
Indiegogo campaign
GitHub
Flattr

söndagen den 8:e april 2012

Playing with Google App Engine's Channel API

Lately I've been playing a lot of StarCraft 2, and while playing I always get this urge to make an RTS game. So this weekend I decided to do it.

Server:
Sadly, WebSockets is not supported on my favorite hosting platform: Google App Engine. Instead they have the "Channel API", geared towards chat applications, multiplayer games, etc. Currently it is based on Comet connections, but it's nicely tucked away under an abstraction layer so they could change that to WebSockets in the future.

The Channel API is dead simple to use:

On the server:
token = channel.create_channel(channel_key)
channel.send_message(channel_key, 'Hello world')

On the client:
<script src="/_ah/channel/jsapi" type="text/javascript">
</script>  
<script>
    channel = new goog.appengine.Channel('{{ token }}');
    socket = channel.open();
    socket.onmessage = function(evt) {
        alert(evt.data); // Hello world!
    };
</script>

Client:
I chose to go with the Canvas2D API that has had a long time to stabilize among different browsers. Also, the game is just boxes and spheres right now as I'm playing around with the game mechanics, so any rendering system would do.

The game:
Two players spawn with 4 circles on each side of the map. The objective is to convert the other players circles which is done by stepping over them when they are not moving. The game is over when one player has all the circles.

Demo:
Ok, maybe not what you would call an RTS game, and the graphics and lack of sound makes it a little boring to watch, but it's a good start!



The code:
The code is open source and is available on GitHub.

fredagen den 4:e november 2011

Building a Great Translation Tool for Youtify

At Youtify we've been talking about making a translation tool for a long time. After all, it doesn't matter how fast or clean our service is if it's in a language people don't understand. Big thanks to Mkaysi and melponene for helping out with the translations so far, but it's time to reach out to the vast majority of people who are not as comfortable dealing with python and git!

This is what we've got so far:


The idea here is to let anyone help out and suggest translations, but as the interface shows, also have team leaders who are responsible for approving them.

Follow the progress in the v11 branch.

fredagen den 3:e juni 2011

How to connect with YouTube via AuthSub on Google App Engine

Want to build an application that lets users connect their YouTube account and then manage playlists, upload videos etc? Read on...

This tutorial will focus on the Google proprietary AuthSub authentication system. The application we will build works like this:
  1. The user clicks on a login link and logs in via their Google Account. This will use the regular users module available to all GAE apps.
  2. Once logged in, they get redirected to YouTube where they are asked to authenticate their YouTube account with our application.
  3. They get returned to our application together with a temporary token.
  4. We upgrade this token to an access token.
  5. We store both the user from step 1, and the access token in the database. Next time the user logs into our site, this token can be reused.
First thing we will do is the main page where we display the options to login or view our playlists:

class MainHandler(webapp.RequestHandler):
    """ Either present option to log in, or if logged in, list playlists """
    def get(self):
        user = users.get_current_user()
        if (user):
            self.response.out.write('<a href="%s">Logout %s</a>' % (users.create_logout_url('/'), user.nickname()))
            self.response.out.write('<br />')
            self.response.out.write('<a href="/list">My Playlists</a>')
        else:
            self.response.out.write('<a href="%s">Login</a>' % users.create_login_url('/login'))

If the user clicks 'login', we use the regular GAE users module to log them in using their Google Account. Once logged in, we forward them to YouTube where they have to authorize our example app.

class LoginHandler(webapp.RequestHandler):
    """ Redirect user to YouTube for an access token """
    def get(self):
        if User.all().filter('user =', users.get_current_user()).fetch(1):
            self.redirect('/')
        else:
            client = YouTubeService()
            gdata.alt.appengine.run_on_appengine(client)
            callback = 'http://' + self.request.environ['HTTP_HOST'] + '/callback';
            url = client.GenerateAuthSubURL(callback, 'http://gdata.youtube.com', secure=False, session=True)
            self.redirect(str(url))

If they click "yes", they get redirected back to our app on the /callback URL. In the URL, there's a one time temporary token. We exchange this token to the correct access token which we will use later when we get the playlists.

class CallbackHandler(webapp.RequestHandler):
    """ User comes back from YouTube with a temporary token that we upgrade """
    def get(self):
        client = YouTubeService()
        gdata.alt.appengine.run_on_appengine(client)
        tmp_token = gdata.auth.extract_auth_sub_token_from_url(self.request.url)
        token = client.upgrade_to_session_token(tmp_token)
        m = User(token=str(token))
        m.put()
        self.redirect('/')

Now we have the Google user mapped to an access token, and can now get our playlists in the '/list' view!


class ListHandler(webapp.RequestHandler):
    """ List playlists of the logged in user """
    def get(self):
        user = User.all().filter('user =', users.get_current_user()).fetch(1)[0]
        url = 'http://gdata.youtube.com/feeds/api/users/default/playlists?v=2&alt=json'
        result = urlfetch.fetch(url, headers={
            'Authorization': user.token,
        })
        json = simplejson.loads(result.content)

        self.response.out.write('<h3>My Playlists</h3>')
        self.response.out.write('<ul>')
        for entry in json['feed']['entry']:
            self.response.out.write('<li>' + entry['title']['$t'] + '</li>')
        self.response.out.write('</ul>')



Complete source code is available on GitHub!

fredagen den 4:e februari 2011

Language Detection with Google Translate

Have you ever been in a situation where you need to know which language some text is in? This is something that can easily be done with the Google Translate API.

Step 1
If you haven't already, you need to register at Google for an API key.

Step 2
Add the Google JavaScript API to your <head> element. Insert the key from step 1.

<head>
    ...
    <script src="https://www.google.com/jsapi?key=INSERT-YOUR-KEY"></script>
    ...
</head>

Step 3
Load v1 of the language module. This goes at the top of your JavaScript file:
google.load("language", "1");

Step 4
Now we're ready to use the API. Let's detect the language of a test string. We put the code in a callback to make sure the Google API is loaded before we start.

google.setOnLoadCallback(function() {
    var stringToTranslate = "Firma Per Thulin";
    google.language.detect(stringToTranslate, function(result) {
        alert(result.language);
    });
});

The alert box would say "sv" in this case. That is the language code for Swedish. If you need to get the name of the language (in english), you can use this map.

The result also contains information on how reliable the detection was:

{
    "language": "sv",
    "isReliable": false,
    "confidence": 0.18470456
}

References:
http://code.google.com/apis/language/translate/v1/getting_started.html
http://code.google.com/apis/language/translate/v1/reference.html

söndagen den 30:e januari 2011

OAuth: A Brief Introduction

OAuth is an open standard for allowing users to share data across different web sites. Such data could for example be your friends list on Facebook or your contacts on GMail. Let's imagine that the web site "test.com" wants to allow users to log in with their Facebook account and then access the users list of friends. This is what test.com has to do:

  1. First test.com has to register on Facebook to get an application id and secret.
  2. test.com then asks Facebook for a request token, providing its app id.
  3. The user is redirected to Facebook in order to authorize the request token. To the user this is presented through a dialog saying something like "do you trust test.com to access your basic information and friends list?".
  4. Facebook redirects the user back to test.com together with an authorization code.
  5. test.com has to verify that it was actually it that sent the user over to Facebook asking for permission. This is done through yet another request to Facebook, providing the previous authorization code together with the application secret. Facebook redirects back to test.com with an access token.
  6. test.com stores the access token and is now free to request the user data from Facebook as long as the access token is provided and the data is something that the user agreed to share with test.com.

It's complex, but it's also a difficult problem and a lot of things to get right. Before OAuth, all the big players had different systems for sharing user data. OAuth simplifies a lot for developers by standardizing the process of sharing user data across web sites, and OAuth 2 simplifies the protocol even further.

This is an exciting time to be doing web development! It's now easier than ever to mashup user data that was previously difficult to extract. For end users we can now dramatically improve the user experience by finally setting a stop to the endless creation of user names and passwords!

So how do I use this on Google App Engine?
Luckily, you don't have to manually go through all the steps described above. Facebook has provided a nice Python module, and with it comes an example for GAE. If it's not Facebook you want to connect with, you should look into the oauth2 Python module.

Resources:
OAuth home page.
Facebooks detailed authorization walkthrough.
Google Tech Talk explaining how OAuth fits in the bigger picture.

måndagen den 24:e januari 2011

How to use the JSLint JavaScript Code Quality Tool


In case you have missed it, I can recommend a tool called JSLint. It goes through your JavaScript for common pitfalls, performance issues and makes sure it's standards compatible.

The first step is to download the jslint.js file. Since it's a JavaScript program, you need a JavaScript interpreter to run it, e.g. Rhino or node.js. This is how you install and run it on an Ubuntu system:

$ apt-get install rhino
$ rhino /path/to/jslint.js /path/to/your/script.js

The output might hurt your feelings, but is a real time saver when hunting down cross-browser issues etc. If you need to tell JSLint about global variables, e.g. the jQuery $ sign, you do so with a special comment at the top of your JavaScript source file:

/*global alert: true, window: true, $: true */

Read more about other options here: www.jslint.com/lint.html

Also, you can use JSLint in the browser just by pasting your code in the text box over at www.jslint.com