Saturday, December 30, 2017

Smallest electron app written in clojurescript

I was toying with GUI app development in Clojure, and I tried Seesaw. It was good, however the startup time of the app didn't please me. So I started off the Electron route instead, and decided to use Clojurescript. Here is how a very tiny electron app written in Clojurescript looks like.

Source files

There will be two sets of source files - some for Clojurescript and some for electron. We start off by creating a project using Leiningen

lein new cljstest1 

We will use the lein-cljsbuild plugin for our convenience, so in addition to modifying the dependencies section in the project.clj file to

  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.9.946"]]

we will also add a plugins section

  :plugins [[lein-cljsbuild "1.1.5"]]

After this an execution of

lein deps

is sufficient to install all dependencies. We will also add some more options to the project.clj file, and what it looks like at the end is this.

The project.clj file

(defproject cljstest1 "0.1.0-SNAPSHOT"
  :description "FIXME: write description"
  :url "http://example.com/FIXME"
  :license {:name "Eclipse Public License"
            :url "http://www.eclipse.org/legal/epl-v10.html"}
  :dependencies [[org.clojure/clojure "1.8.0"]
                 [org.clojure/clojurescript "1.9.946"]]
  :plugins [[lein-cljsbuild "1.1.5"]]
  :cljsbuild {
    :builds [{ :id "default"
               :source-paths ["src"]
           :compiler {
                 :output-to "app/app.js"
                 :target :nodejs
                 :main cljstest1.core
                 :optimizations :simple
                 :pretty-print true
                 :externs ["externs.js"]
               }
             }
    ]
  }
 ) 

As you can see we plan to generate the Electron app in app/app.js. The directory 'app' will be created soon. Before we forget we need to create the externs.js file which we will need in order to use __dirname from Clojurescript.

The externs.js file

var __dirname;

The core.cljs file

Leiningen generated a src/core.clj file for us. Let's rename it to core.cljs so that the cljsbuild tool finds it automatically. Here is what it looks like.

(ns cljstest1.core
     (:require [cljs.nodejs :as nodejs]))

(def electron-pkg (nodejs/require "electron"))
(def url-pkg (nodejs/require "url"))
(def path-pkg (nodejs/require "path"))

(defn create-window
  []
    (.
      (new
        electron-pkg.BrowserWindow
        #js
        {:width 800 :height 600}
      )
      loadURL (url-pkg.format
               #js
                {:pathname (path-pkg.join js/__dirname "index.html")
                 :protocol "file"
                 :slashes true
                 }
               )
      )
)

(defn -main
  []
  (.on  (.-app electron-pkg) "ready" create-window)
)

(set! *main-cli-fn* -main)

The last line which updates the *main-cli-fn* variable is a very important part. Without that node.js won't be able to run the app.

After the Clojurescript part we need to generate the Electron part of our source. We need to create a directory 'app', and inside it place the following package.json file

The package.json file

{
  "name": "app",
  "version": "1.0.0",
  "description": "",
  "main": "app.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "electron ."
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
      "electron": "~1.7.8"
  }
}

In this directory, we will also place a index.html file

The index.html file

<html>
  <body>
    <h1>
Ha!</h1>
</body>
<html>

Steps to compile and run

  1. cd app; npm install; cd ..
  2. lein cljsbuild once
  3. cd app; npm start

Monday, November 6, 2017

World's smallest hugo site

I have been playing with Hugo for a while and it is
  • easy to set up
  • fast
  • flexible
  • well-documented
Here's how to create a tiny single-page website using Hugo.

Generate the source code to the site

Create a directory for the source code, and give this command

hugo new site <directory-name>

Add some basic customization

Go to the source code directory and open up config.toml and edit any field you want to. If you don't it is fine. Generally I disable unnecessary stuff like RSS feeds etc, so I add

disableKinds = ["RSS"]

 I also want to control where the generated website goes, so I add

publishDir = <directory-path-within-quotes>

Create the html page

Here is a simple html page for starters

<html>
  <head>
    <title>
      Home page of XYZ

    </title>
  </head>
  <body>
    Nothing of importance at the moment
  </body>
</html>

Save it to layouts/index.html

Generate the site

The command is, simply

hugo

That's it. Your website is generated in the output directory 'public' or the value of the variable publishDir if you changed it.

Notes

I know that this is probably not the prescribed way of using a static site generator. Most people are talking about a separation of concerns, where your theme and layout are not connected with your content. I feel that that should not be the only way to create websites. It is possible for content and layout to be mixed for very small sites. Or when you start building the site. Later on you can gradually move the content out and create a stand-alone layout.

Sunday, November 5, 2017

World's smallest electron app

Electron seems to be a very easy-to-setup system if you already have node.js and npm. I could get a small app running even on Windows. Here's what you do.

Create a package.json file

You can use 'npm init' for this, or just your text editor. The example I can give is

{
  "name": "electron1",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "electron .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "electron": "~1.7.8"
  }
}

Create an index.html file

This will be the default screen of the app. The example I can give is

<html>
  <body>
    <h1>
Ha!</h1>
</body>
</html>

Create a index.js file

This will be the code behind the app. The example I have is

var electron = require('electron')
var app = electron.app

var path = require('path')
var url = require('url')

let mainWindow


function createWindow () {
  // Create the browser window.
  mainWindow = new electron.BrowserWindow({width: 800, height: 600})

  // and load the index.html of the app.
  mainWindow.loadURL(url.format({
    pathname: path.join(__dirname, 'index.html'),
    protocol: 'file:',
    slashes: true
  }))
 
    // Emitted when the window is closed.
  mainWindow.on('closed', function () {
    // Dereference the window object, usually you would store windows
    // in an array if your app supports multi windows, this is the time
    // when you should delete the corresponding element.
    mainWindow = null
  })
}

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on('ready', createWindow)

Launch the app

There is a one-time command you need to execute:

npm install

After that is done you can launch your app using

npm start

Credits

This is nothing but a reduced version of the Electron quick-start app

Wednesday, November 2, 2016

Writing a web app

Recently I have started writing a web app, which I was trying to build for a long time. This time I am much more closer to completion than ever before, and I feel I can easily complete it.
I want to think about why I couldn't do this for a long time, and why I have done a large part of it in a couple of weekends. Possible reasons coming to my mind are:

  • I was misguided by many blog posts
  • I made my first attempt using PHP, just because I knew the language
  • I was focusing on the wrong part of the app
  • My day job and my life in India was draining out all of my energy
  • I was trying to do too many things and not doing most of them
I'll know better when I actually get to launching the first version of the app. So far, here are my learnings:
  • Prefer podcasts over blog posts, if you have learn from the net
  • Put highest preference to books - buy them or loan them from a library - they are worth every penny
  • Start your prototype as a front-end app, using html and javascript. Use jquery extensively.
  • Use a Javascript array as your database, to begin with. It will be good enough for most prototypes.
  • If you are stuck, stop and read a book or discuss with someone
  • Don't start with any app framework - you don't know what you need.
I'll stop here and resume when I have made more progress

Friday, October 28, 2016

My Javascript workflow

So I am trying out my hand in JavaScript, and want to talk about my workflows. I have two development setups - one on a cloud VM which is a DigitalOcean droplet, and the other is my laptop which happens to run Windows (since it is provided by my office).

On the cloud machine development is super easy. I connect to it using putty from Windows, and write my code using emacs, and run a python server (python -m SimpleHTTPServer) in another shell. I run both these shells inside a screen session which I keep alive, and detach when I logout. I can view pages served by the web server on my local machine's web browser by going to my VM's IP address and using the port 8000 which is what the python module uses by default.

On my Windows laptop it seems things are not that hard. I write my code using Notepad++ or Brackets, and run a node server (http-server.cmd) from the Windows PowerShell. I can view the web pages on my web browser by going to http://lopcalhost:8080 as 8080 is the port used by the node.js module. The Windows port of node.js looks pretty good, which means a lot of web development can be done on PCs now. How do I use git? Well github has a Windows desktop client which makes development in github repositories a breeze!

Tuesday, October 11, 2016

Poster inspired by podcast on abstractions

I am being mindblown by the world of podcasts, and programming podcasts in particular. Today I heard this episode of "this developer's life" where there was a nice quote at the end. I decided to make a poster out of it.

Wednesday, September 21, 2016

Revisiting Javascript

Javascript was the first programming language I learnt, back in 2001, about to leave high school. In college I somehow 'learnt' that these were not real programming languages. The real languages were C, C++, Java and the like. I gradually drifted towards C++, and then worked in C and C++ for a decade in the industry.

Now I am stumbling upon one thing after the other about Javascript which makes me think - god why didn't any of the tutorials tell me all this back in 2001! Specially about the bits of functional programming possible in Javascript - and how you can quickly built complex programs with it.

I just want to list down the nice things I've encountered in the past few days:
1. A blog about how to write a programming language in Javascript
2. Marijn Haverbeke's book 'Eloquent Javascript'
3. A talk from EmpireJS on Knitting in Javascript
4. A 30-line implementation of a simple spreadsheet in Javascript
5. A blog post about variable scoping in Javascript

The language is confused and allows multiple paradigms - but so is C++. The best thing about Javascript is that it is much easier to use functional programming techniques in it. And the even better thing is that most devices/platforms seem to be supporting it. I am tending to believe that the bigger things of the future will be built upon powerful programming languages or systems. I am gradually moving away from the importance of building faster low-level programming systems.