Skip to content

Instantly share code, notes, and snippets.

@webcoyote
Created January 30, 2019 02:54
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save webcoyote/f750fbe978f8af548284cd72ff2a2820 to your computer and use it in GitHub Desktop.
Save webcoyote/f750fbe978f8af548284cd72ff2a2820 to your computer and use it in GitHub Desktop.
Planck (ClojureScript) script demonstrating difficulty of "self-referencing scripts"
#!/usr/bin/env bash
"exec" "plk" "-Sdeps" "{:deps {org.clojure/tools.cli {:mvn/version \"0.4.1\"}}}" "-Ksf" "${BASH_SOURCE[0]}" "--script" "${BASH_SOURCE[0]}" "$@"
;; # This program was written to utilize the Planck ClojureScript tool and see how
;; # easy it would be to write command-line utilities.
;; #
;; # One problem I encountered: in bash, it's reasonably easy to discover where
;; # the script is located so as to perform script-relative file manipulation,
;; # like this:
;; #
;; # readonly SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
;; # readonly EXAMPLE_FILE="$(realpath "$SCRIPT_DIR/../project.clj")"
;; # do-something-with "$EXAMPLE_FILE"
;; #
;; # In planck we must write a bash preamble that execs the ClojureScript interpreter
;; # with an argument that can be used to locate the script, and then include a lot
;; # of boilerplate code to parse the argument.
;; #
;; # "--script" "${BASH_SOURCE[0]}"
;; #
;; # Moreover, this messes with auto-detection of file type by text-editors,
;; # which is why this file uses ";; #" for comments!
;; #
;; # What would be really nice is a shorthand equivalent in Planck for "${BASH_SOURCE[0]}"
(ns my.program
(:require
[clojure.string :as string]
[clojure.tools.cli :refer [parse-opts]]
[planck.core :as core]))
;; # Usage
(def cli-options
[["-s" "--script DIRECTORY" "Path to this script"]
["-h" "--help"]])
;; # path functions
(defn base-name [filename]
(re-find #"[^/]+$" filename))
(defn dir-name [filename]
(string/join "/" (or (butlast (string/split filename "/")) ["."])))
(defn make-path [directory filename]
(str directory "/" filename))
;; # Parse the command line
(def opts (parse-opts cljs.core/*command-line-args* cli-options))
(when-let [errors (:errors opts)]
(do (println "ERROR: failed to parse command-line:")
(println errors)
(core/exit 1)))
(defn script-name []
(get-in opts [:options :script]))
(defn script-dir []
(dir-name (script-name)))
(when (get-in opts [:options :help])
(do (println "Usage:" (base-name (script-name)) "[options]")
(println (:summary opts))))
;; # Finally -- the actual script
(println "script-dir: " (script-dir))
(println "script-name:" (script-name))
(println "base-name: " (base-name (script-name)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment