DEV Community

Discussion on: Joker: Flex Your Scripting Muscles In (Almost) Clojure

Collapse
 
hlship profile image
Howard M. Lewis Ship • Edited

I wasn't sure quite how to weave this into the narrative, but at one point I wrote a 20 line Python script that parsed some arguments and figured out the exact docker command to run for me. It was mostly for my own personal use, but I shared it with the rest of the team.

I did it in Python just because Python had a good built-in library for parsing command line options.

This triggered a multi-person-hour discussion about the merits of one language vs. another, whether it was appropriate to introduce yet another language into the system (beyond Clojure, Ruby, and some Bash scripts) and so forth. Ultimately, someone rewrote it as a Bash script, adding in nearly 100 lines of boilerplate, mostly dealing with parsing the command line options.

I kept my personal copy of the Python version.

Anyway, it's great to have a familiar, functional, fast scripting option ... with great command line arguments parsing.

Collapse
 
dpritchett profile image
Daniel Pritchett ⚡

Really appreciated this post! I'd been trying to find a good clojurish replacement to my sprawling ~/bin folder full of bash and ruby stuff. I tried lumo a bit but didn't really enjoy it. Joker is working out well!

Is there any way to find other folks' joker code in the wild? The API docs are nice but I could really use a lot more examples.

Collapse
 
hlship profile image
Howard M. Lewis Ship

Most of my Joker code is internal, but here's something I've put together for my own purposes.

github.com/hlship/dialog-tool

It's pretty much the kind of brutal, pragmatic kind of code you'd put in a Bash script, but in Joker, and it runs fast and nice.

Thread Thread
 
dpritchett profile image
Daniel Pritchett ⚡

Appreciate it, thank you.

Thread Thread
 
dpritchett profile image
Daniel Pritchett ⚡ • Edited

Having a good time now - this is probably the first time I've actually gotten value out of Clojure at work in ten years of wishing :P

Silly convenience wrappers:

> cat ~/bin/jokes/lib/shell.joke
#!/usr/bin/env /usr/local/bin/joker

(ns lib.shell (:require [joker.os :refer [exec sh]]))

(defn sh-v
  "Verbosely execute a script via joker.os/sh."
  [bin & args]
    (apply println "Executing:\t" bin args)
    (apply sh bin args)
    (println "Complete."))

(defn exec-v
  "Verbosely execute a script via joker.os/exec."
  [bin args]
  (let [opts { :args args :stdin *in* :stdout *out* :err *err*}]
    (apply println "Executing:\t" bin args)
    (let [result (exec bin opts)]
      (println result)
      (println "Complete."))))

Usage:

> cat wtf-docker
#!/usr/bin/env /usr/local/bin/joker

(ns script
  (:require [lib.cli :refer [argv-str]]
            [lib.shell :as shell]))

(defn docker-shell
  "Open a bash shell inside the supplied docker tag or hash."
  [tag-or-hash]
  (let
    [sh-args ["run" "-ti" tag-or-hash "/bin/bash" "--login"]]
    (shell/exec-v "docker" sh-args)))

(def results (docker-shell argv-str))

(println results)

Demo:

> wtf-docker ubuntu:latest
Executing:   docker run -ti ubuntu:latest /bin/bash --login
root@b84798f0415c:/# logout
{:success true, :exit 0, :err }
Complete.
nil