Skip to content

Latest commit

 

History

History
557 lines (412 loc) · 15 KB

README.md

File metadata and controls

557 lines (412 loc) · 15 KB

Examples

Here's a gallery of useful examples. Do you have a useful example? PR welcome!

Delete a list of files returned by a Unix command

find . | grep conflict | bb -i '(doseq [f *input*] (.delete (io/file f)))'

Calculate aggregate size of directory

#!/usr/bin/env bb

(as-> (io/file (or (first *command-line-args*) ".")) $
  (file-seq $)
  (map #(.length %) $)
  (reduce + $)
  (/ $ (* 1024 1024))
  (println (str (int $) "M")))
$ dir-size
130M

$ dir-size ~/Dropbox/bin
233M

Shuffle the lines of a file

$ cat /tmp/test.txt
1 Hello
2 Clojure
3 Babashka
4 Goodbye

$ < /tmp/test.txt bb -io '(shuffle *input*)'
3 Babashka
2 Clojure
4 Goodbye
1 Hello

Fetch latest Github release tag

(require '[clojure.java.shell :refer [sh]]
         '[cheshire.core :as json])

(defn babashka-latest-version []
  (-> (sh "curl" "https://api.github.com/repos/babashka/babashka/tags")
      :out
      (json/parse-string true)
      first
      :name))

(babashka-latest-version) ;;=> "v0.0.73"

Generate deps.edn entry for a gitlib

#!/usr/bin/env bb

(require '[clojure.java.shell :refer [sh]]
         '[clojure.string :as str])

(let [[username project branch] *command-line-args*
      branch (or branch "master")
      url (str "https://github.com/" username "/" project)
      sha (-> (sh "git" "ls-remote" url branch)
              :out
              (str/split #"\s")
              first)]
  {:git/url url
   :sha sha})
$ gitlib.clj nate fs
{:git/url "https://github.com/nate/fs", :sha "75b9fcd399ac37cb4f9752a4c7a6755f3fbbc000"}
$ clj -Sdeps "{:deps {fs $(gitlib.clj nate fs)}}" \
  -e "(require '[nate.fs :as fs]) (fs/creation-time \".\")"
#object[java.nio.file.attribute.FileTime 0x5c748168 "2019-07-05T14:06:26Z"]

View download statistics from Clojars

Contributed by @plexus.

$ curl https://clojars.org/stats/all.edn |
bb -o '(for [[[group art] counts] *input*] (str (reduce + (vals counts))  " " group "/" art))' |
sort -rn |
less
14113842 clojure-complete/clojure-complete
9065525 clj-time/clj-time
8504122 cheshire/cheshire
...

Portable tree command

See examples/tree.clj.

$ clojure -Sdeps '{:deps {org.clojure/tools.cli {:mvn/version "0.4.2"}}}' examples/tree.clj src
src
└── babashka
    ├── impl
    │   ├── tools
    │   │   └── cli.clj
...

$ examples/tree.clj src
src
└── babashka
    ├── impl
    │   ├── tools
    │   │   └── cli.clj
...

List outdated maven dependencies

See examples/outdated.clj. Inspired by an idea from @seancorfield.

$ cat /tmp/deps.edn
{:deps {cheshire {:mvn/version "5.8.1"}
        clj-http {:mvn/version "3.4.0"}}}

$ examples/outdated.clj /tmp/deps.edn
clj-http/clj-http can be upgraded from 3.4.0 to 3.10.0
cheshire/cheshire can be upgraded from 5.8.1 to 5.9.0

Convert project.clj to deps.edn

Contributed by @plexus.

$ cat project.clj |
sed -e 's/#=//g' -e 's/~@//g' -e 's/~//g' |
bb '(let [{:keys [dependencies source-paths resource-paths]} (apply hash-map (drop 3 *input*))]
  {:paths (into source-paths resource-paths)
   :deps (into {} (for [[d v] dependencies] [d {:mvn/version v}]))}) ' |
jet --pretty > deps.edn

A script with the same goal can be found here.

Print current time in California

See examples/pst.clj

Tiny http server

This implements an http server from scratch. Note that babashka comes with org.httpkit.server now, so you don't need to build an http server from scratch anymore.

See examples/http_server_from_scratch.clj

Original by @souenzzo

Print random docstring

See examples/random_doc.clj

$ examples/random_doc.clj
-------------------------
clojure.core/ffirst
([x])
  Same as (first (first x))

Cryptographic hash

sha1.clj:

#!/usr/bin/env bb

(defn sha1
  [s]
  (let [hashed (.digest (java.security.MessageDigest/getInstance "SHA-1")
                        (.getBytes s))
        sw (java.io.StringWriter.)]
    (binding [*out* sw]
      (doseq [byte hashed]
        (print (format "%02X" byte))))
    (str sw)))

(sha1 (first *command-line-args*))
$ sha1.clj babashka
"0AB318BE3A646EEB1E592781CBFE4AE59701EDDF"

Package script as Docker image

Dockerfile:

FROM babashka/babashka
RUN echo $'\
(println "Your command line args:" *command-line-args*)\
'\
>> script.clj

ENTRYPOINT ["bb", "script.clj"]
$ docker build . -t script
...
$ docker run --rm script 1 2 3
Your command line args: (1 2 3)

Extract single file from zip

;; Given the following:

;; $ echo 'contents' > file
;; $ zip zipfile.zip file
;; $ rm file

;; we extract the single file from the zip archive using java.nio:

(import '[java.nio.file Files FileSystems CopyOption])
(let [zip-file (io/file "zipfile.zip")
      file (io/file "file")
      fs (FileSystems/newFileSystem (.toPath zip-file) nil)
      file-in-zip (.getPath fs "file" (into-array String []))]
  (Files/copy file-in-zip (.toPath file)
              (into-array CopyOption [])))

Note taking app

See examples/notes.clj. This is a variation on the http-server example. If you get prompted with a login, use admin/admin.

which

The which command re-implemented in Clojure. See examples/which.clj. Prints the canonical file name.

$ examples/which.clj rg
/usr/local/Cellar/ripgrep/11.0.1/bin/rg

pom.xml version

A script to retrieve the version from a pom.xml file. See pom_version_get.clj. Written by @wilkerlucio.

See pom_version_get_xml_zip.clj for how to do the same using zippers.

Also see pom_version_set.clj to set the pom version.

Whatsapp frequencies

Show frequencies of messages by user in Whatsapp group chats. See examples/whatsapp_frequencies.clj

Find unused vars

This script invokes clj-kondo, stores returned data in an in memory HSQLDB database and prints the result of a query which finds unused vars. It uses pod-babashka-hsqldb.

$ bb examples/hsqldb_unused_vars.clj src

|                   :VARS/NS |               :VARS/NAME |                     :VARS/FILENAME | :VARS/ROW | :VARS/COL |
|----------------------------|--------------------------|------------------------------------|-----------|-----------|
| babashka.impl.bencode.core |           read-netstring | src/babashka/impl/bencode/core.clj |       162 |         1 |
| babashka.impl.bencode.core |          write-netstring | src/babashka/impl/bencode/core.clj |       201 |         1 |
|      babashka.impl.classes | generate-reflection-file |      src/babashka/impl/classes.clj |       230 |         1 |
|    babashka.impl.classpath |      ->DirectoryResolver |    src/babashka/impl/classpath.clj |        12 |         1 |
|    babashka.impl.classpath |        ->JarFileResolver |    src/babashka/impl/classpath.clj |        37 |         1 |
|    babashka.impl.classpath |                 ->Loader |    src/babashka/impl/classpath.clj |        47 |         1 |
| babashka.impl.clojure.test |            file-position | src/babashka/impl/clojure/test.clj |       286 |         1 |
| babashka.impl.nrepl-server |             stop-server! | src/babashka/impl/nrepl_server.clj |       179 |         1 |
|              babashka.main |                    -main |              src/babashka/main.clj |       485 |         1 |

List contents of jar file

For the code see examples/ls_jar.clj.

$ ls_jar.clj borkdude/sci 0.0.13-alpha.24
META-INF/MANIFEST.MF
META-INF/maven/borkdude/sci/pom.xml
META-INF/leiningen/borkdude/sci/project.clj
...

Invoke vim inside a script

See examples/vim.clj.

Portal

This script uses djblue/portal for inspecting EDN, JSON, XML or YAML files.

Example usage:

$ examples/portal.clj ~/git/clojure/pom.xml

See portal.clj.

Image viewer

Opens browser window and lets user navigate through images of all sub-directories.

Example usage:

$ examples/image-viewer.clj

See image-viewer.clj.

HTTP Server

Opens browser window and lets user navigate through filesystem, similar to python3 -m http.server.

Example usage:

$ examples/http-server.clj

See file-server.clj.

Torrent viewer

Shows the content of a torrent file. Note that pieces' content is hidden.

Example usage:

$ examples/torrent-viewer.clj file.torrent

See torrent-viewer.clj.

This script uses tolitius/cprop library.

See cprop.clj

Example usage:

$ ( cd examples && bb cprop.clj )

Invoke fzf, a command line fuzzy finder, from babashka.

See fzf.clj

Example usage:

$ cat src/babashka/main.clj | bb examples/fzf.clj

The script allows to define which DigitalOcean cloud datacenter (region) has best network performance (ping latency).

See digitalocean-ping.clj

Example usage:

$ bb digitalocean-ping.clj

Download deps for all aliases in a deps.edn project.

An equivalent of Python's os.isatty() in Babashka, to check if the stdin/stdout/stderr is connected to a TTY or not (useful to check if the script output is being redirect to /dev/null, for example).

Only works in Unix systems.

$ bb is-tty.clj
STDIN is TTY?: true
STDOUT is TTY?: true
STDERR is TTY?: true

$ bb is-tty.clj </dev/null
STDIN is TTY?: false
STDOUT is TTY?: true
STDERR is TTY?: true

$ bb is-tty.clj 1>&2 >/dev/null
STDIN is TTY?: true
STDOUT is TTY?: false
STDERR is TTY?: true

$ bb is-tty.clj 2>/dev/null
STDIN is TTY?: true
STDOUT is TTY?: true
STDERR is TTY?: false

Provide a Clojure file to the script and it will print the Clojure file with auto-resolved keywords normalized to fully qualified ones without double colons: ::set/foo becomes :clojure.set/foo.

$ cat /tmp/test.clj
(ns test (:require [clojure.set :as set]))

[::set/foo ::bar]

$ bb examples/normalize-keywords.clj /tmp/test.clj
(ns test (:require [clojure.set :as set]))

[:clojure.set/foo :test/bar]

Check stdin for data

# when piping something in, we get a positive number
$ echo 'abc' | bb '(pos? (.available System/in))'
true
# even if we echo an empty string, we still get the newline
$ echo '' | bb '(pos? (.available System/in))'
true
# with nothing passed in, we finally return false
$ bb '(pos? (.available System/in))'
false

Using org.clojure/data.xml

xml-example.clj explores some of the capabilities provided by the org.clojure/data.xml library (required as xml by default in Babashka). While running the script will show some output, reading the file shows the library in use.

$ bb examples/xml-example.clj
... some vaguely interesting XML manipulation output

Simple logger

logger.clj is a simple logger that works in bb.

$ bb "(require 'logger) (logger/log \"the logger says hi\")"
<expr>:1:19 the logger says hi 

Using GZip streams to make a note utility

memo.clj creates zip files in /tmp for stashing notes (possibly the most inefficient KV store ever)

$ echo "8675309" | memo.clj put jenny
ok
$ memo.clj get jenny
8675309

Pretty-printing mySQL results

db_who.clj will query mysql for all the connected sessions and pretty-print the user and what program they're using.

$ bb db_who.clj
|             user |   program_name |
|------------------+----------------|
|   root@localhost |          mysql |
| fred@192.168.1.2 |      workbench |
| jane@192.168.1.3 | Toad for mySQL |

Single page application with Babashka + htmx

Example of a todo list SPA using Babashka and htmx See htmx_todoapp.clj

Contributed by @prestancedesign.