# API wrapper for Clojure

I wanted to wrap the jkeymaster library in a Clojure wrapper (for my own use, but perhaps also to save others some time). I'm just learning Clojure so I'm still not quite sure what "idiomatic libraries/APIs" look like. In Ruby, I would have created an object with methods, but in one of the clojure books they recommended letting users manage state themselves, so I have function that creates a provider, and this provider must then be passed to the register function.

Here's first an example of usage:

(ns keymaster.core
(:require [keymaster.keymaster :as km]))
(defn -main
"I don't do a whole lot ... yet."
[& args]
(km/register (km/provider) "control shift 1" #(println "hi")))


And here is the full text of the "library".

(ns keymaster.keymaster
(:gen-class)
(:use (com.tulskiy.keymaster.common)))

(defn provider []
"Gets and initiates a keymaster provider, which must be passed to register to register shortcuts"
(let [provider (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)]
(.init provider)
provider))

(defn- conv-keystroke [x]
"Takes keystroke in the form \"control shift 1\" and returns a Keystroke class"
(javax.swing.KeyStroke/getKeyStroke x))

(defn- conv-listener [f]
"Takes a function with one argument, which will get passed the keycode, and creates a listener
Todo: How to accept a function with or without a parameter to accept hotKey?"
(proxy [com.tulskiy.keymaster.common.HotKeyListener] [] (onHotKey [hotKey] (f))))

(defn register
[provider shortcut listener]
"Registers a shortcut on provider, which will trigger listener (with one argument)"
(let [k (conv-keystroke shortcut)
l (conv-listener listener)]
(.register provider k l)))


In addition to any general style feedback, both about the coding, and the design of the API, I'm also wondering if there is any way to have conv-listener accept either a 0 or 1-arity function. Right now I made the choice of accepting a 0-arity function, but if someone wanted to pass a 1-arity function, where the first argument would be the name of the keycode called (hotKey), which I would call with (f hotKey), I would have to rewrite... Possible to allow both? (1-arity is inconvenient for anonymous functions where we really don't need it - which I suspect is most of the time, since we can bind different hotkeys to different listeners).

• I rewrote slightly to have provider instead return a (partial register provider), which the user can then use to register a new key directly, thus exposing only one function to the user. github.com/houshuang/keymaster-clj - still interested in feedback Apr 30, 2013 at 2:13
• Got a nice GitHub pull request (another form of code review), and a substantially nicer function is now available - also as a Clojar. But still happy to receive feedback here. May 2, 2013 at 2:53

## 1 Answer

As a wrapper goes I think this looks fine. The feedback I do have is that I wouldn't use let as often as you do and would use the treading macro (-> ...) instead.

For example:

(-> (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)
.init)


does the same as

(let [provider (com.tulskiy.keymaster.common.Provider/getCurrentProvider true)]
(.init provider)
provider)


and it's easier to read and shorter. You could also do it this way:

(.init (com.tulskiy.keymaster.common.Provider/getCurrentProvider true))