├── test └── practicalli │ └── random_clojure_function_test.clj ├── CHANGELOG.md ├── .gitignore ├── README.md ├── deps.edn ├── .github └── workflows │ └── clojure.yaml └── src └── practicalli └── random_clojure_function.clj /test/practicalli/random_clojure_function_test.clj: -------------------------------------------------------------------------------- 1 | (ns practicalli.random-clojure-function-test 2 | (:require 3 | [clojure.test :refer [deftest is testing]] 4 | [practicalli.random-clojure-function :as SUT])) 5 | 6 | 7 | (deftest random-function-test 8 | (testing "Show random function from Clojure standard library" 9 | (is (seq SUT/standard-library-functions)) 10 | (is (string? (SUT/random-function SUT/standard-library-functions))))) 11 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Change Log 2 | All notable changes to this project will be documented in this file. This change log follows the conventions of [keepachangelog.com](http://keepachangelog.com/). 3 | 4 | ## [Unreleased] 5 | 6 | ### Changed 7 | - dev: update Clojure library to version 1.12.0 8 | 9 | ## 2023-09-14 10 | ### Changed 11 | - add build.clj to define tasks to build the project 12 | - add `:test/run` alias for kaocha test runner 13 | - add `:built/task` alias to include Clojure tools.build library 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # ------------------------ 2 | # Clojure Project Git Ignore file patterns 3 | # 4 | # Ignore all except patterns starting with ! 5 | # Add comments on separate lines, not same line as pattern 6 | # ------------------------ 7 | 8 | # ------------------------ 9 | # Ignore everthing in root directory 10 | /* 11 | 12 | # ------------------------ 13 | # Common project files 14 | !CHANGELOG.md 15 | !README.md 16 | 17 | # ------------------------ 18 | # Include Clojure project & config 19 | !build.clj 20 | !deps.edn 21 | !pom.xml 22 | !dev/ 23 | !docs/ 24 | !resources/ 25 | !src/ 26 | !test/ 27 | 28 | # ------------------------ 29 | # Include Clojure tools 30 | !.cljstyle 31 | !.dir-locals.el 32 | !compose.yaml 33 | !Dockerfile 34 | !.dockerignore 35 | !Makefile 36 | !tests.edn 37 | 38 | # ------------------------ 39 | # Include Git & CI workflow 40 | !.gitattributes 41 | !.gitignore 42 | !.github/ 43 | 44 | # ------------------------ 45 | # Include ClojureScript Figwheel 46 | !figwheel-main.edn 47 | !*.cljs.edn 48 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # random-clojure-function 2 | An application that returns a random function name and description from the Clojure standard library 3 | 4 | [![CircleCI](https://circleci.com/gh/circleci/circleci-docs.svg?style=svg)](https://circleci.com/gh/practicalli/random-clojure-function) 5 | 6 | 7 | ## Installation 8 | Download from https://github.com/practicalli/random-clojure-function. 9 | 10 | 11 | ## Development 12 | Open the `src/practicalli/random-clojure-function.clj` file in a Clojure editor, evaluate the whole namespace. 13 | 14 | Cognitect Labs test runner is included in the `deps.edn` project configuration, for running all tests 15 | ```shell 16 | clojure -A:test:runner 17 | ``` 18 | 19 | Run the application on the command line: 20 | ```shell 21 | clojure -m practicalli.random-clojure-function 22 | ``` 23 | 24 | The application can take arguments that are names of namespaces available in the [Clojure Standard Library](https://clojure.github.io/clojure/). 25 | ```shell 26 | clojure -m practicalli.random-clojure-function "clojure.string" "clojure.repl" 27 | ``` 28 | 29 | 30 | ## Deployment 31 | Package the application into a JVM jar file, creating an uberjar that contains the application and the Clojure standard library. 32 | 33 | ```shell 34 | clojure -A:uberjar-depstar 35 | ``` 36 | 37 | Run the application from the uberjar: 38 | ```shell 39 | $ java -jar random-clojure-function.jar 40 | ``` 41 | 42 | ## License 43 | Copyright © 2020 Practicalli 44 | 45 | Distributed under the Creative Commons Attribution Share-Alike 4.0 International 46 | -------------------------------------------------------------------------------- /deps.edn: -------------------------------------------------------------------------------- 1 | {;; ------------------------------------------ 2 | ;; Source code paths 3 | :paths 4 | ["src" "resources"] 5 | ;; ------------------------------------------ 6 | 7 | ;; ------------------------------------------ 8 | ;; Main dependencies 9 | :deps 10 | {org.clojure/clojure {:mvn/version "1.12.0"}} 11 | ;; ------------------------------------------ 12 | 13 | :aliases 14 | {;; ------------------------------------------ 15 | ;; Run application and functions 16 | 17 | :run/main {:main-opts ["-m" "practicalli.random-function"]} 18 | 19 | :run/greet {:ns-default practicalli.random-function 20 | :exec-fn greet 21 | :exec-args {:name "Clojure"}} 22 | ;; ------------------------------------------ 23 | 24 | ;; ------------------------------------------ 25 | ;; Testing 26 | :test/env 27 | {:extra-paths ["test"] 28 | :extra-deps {org.clojure/test.check {:mvn/version "1.0.0"}}} 29 | 30 | ;; Test runner - local and CI 31 | ;; call with :watch? true to start file watcher and re-run tests on saved changes 32 | :test/run 33 | {:extra-paths ["test"] 34 | :extra-deps {lambdaisland/kaocha {:mvn/version "1.85.1342"}} 35 | :main-opts ["-m" "kaocha.runner"] 36 | :exec-fn kaocha.runner/exec-fn 37 | :exec-args {:randomize? false 38 | :fail-fast? true}} 39 | ;; ------------------------------------------ 40 | 41 | ;; ------------------------------------------ 42 | ;; tools.build `build.clj` tasks 43 | 44 | :build/env {:extra-paths "."} 45 | 46 | :build/task 47 | {:replace-deps {io.github.clojure/tools.build 48 | {:git/tag "v0.9.4" :git/sha "76b78fe"}} 49 | :ns-default build}}} 50 | ;; ------------------------------------------ 51 | -------------------------------------------------------------------------------- /.github/workflows/clojure.yaml: -------------------------------------------------------------------------------- 1 | name: Clojure CLI 2 | 3 | on: 4 | push: 5 | branches: [ "live" ] 6 | pull_request: 7 | branches: [ "live" ] 8 | 9 | jobs: 10 | workflow: 11 | name: workflow-name 12 | runs-on: ubuntu-latest 13 | steps: 14 | - run: echo "🚀 Job automatically triggered by ${{ github.event_name }}" 15 | - run: echo "🐧 Job running on ${{ runner.os }} server" 16 | - run: echo "🐙 Using ${{ github.ref }} branch from ${{ github.repository }} repository" 17 | 18 | - name: Checkout Code 19 | uses: actions/checkout@v3 20 | with: 21 | token: "${{ secrets.PAT || secrets.GITHUB_TOKEN }}" 22 | fetch-depth: 0 # fetch all history 23 | - run: echo "🐙 ${{ github.repository }} repository was cloned to the runner." 24 | 25 | - name: Prepare java 26 | uses: actions/setup-java@v3 27 | with: 28 | distribution: 'temurin' 29 | java-version: '17' 30 | 31 | - name: Install clojure tools 32 | uses: DeLaGuardo/setup-clojure@12.1 33 | with: 34 | cli: 1.11.1.1413 # Clojure CLI based on tools.deps 35 | cljstyle: 0.15.0 # cljstyle 36 | clj-kondo: 2022.10.05 # Clj-kondo 37 | 38 | - name: Cache clojure dependencies 39 | uses: actions/cache@v3 40 | with: 41 | path: | 42 | ~/.m2/repository 43 | ~/.gitlibs 44 | # List all files containing dependencies: 45 | key: clojure-deps-${{ hashFiles('deps.edn') }} 46 | restore-keys: clojure-deps- 47 | 48 | - name: Run Unit tests 49 | run: clojure -X:test/run :fail-fast? false 50 | 51 | - name: "Lint with clj-kondo" 52 | run: clj-kondo --lint deps.edn src resources test --config .clj-kondo/config-ci.edn 53 | 54 | - name: "Check Clojure Style" 55 | run: cljstyle check --report 56 | 57 | - name: Package Clojure project 58 | run: clojure -T:build/task uberjar 59 | 60 | # Summary and status 61 | - run: echo "🎨 Workflow name completed" 62 | - run: echo "🍏 Job status is ${{ job.status }}." 63 | -------------------------------------------------------------------------------- /src/practicalli/random_clojure_function.clj: -------------------------------------------------------------------------------- 1 | (ns practicalli.random-clojure-function 2 | (:gen-class)) 3 | 4 | 5 | ;; data 6 | 7 | (def standard-library-functions 8 | "Fully qualified function names from clojure.core" 9 | (vals (ns-publics 'clojure.core))) 10 | 11 | 12 | (def all-public-functions 13 | "Fully qualified function names from available" 14 | (mapcat #(vals (ns-publics %)) (all-ns))) 15 | 16 | 17 | ;; helper functions 18 | 19 | (defn function-list 20 | [namespace] 21 | (vals (ns-publics namespace))) 22 | 23 | 24 | (defn selective-namespace-functions 25 | [namespace-sequence] 26 | (mapcat #(function-list (symbol %)) namespace-sequence)) 27 | 28 | 29 | ;; logic 30 | 31 | (defn random-function 32 | [function-list] 33 | (let [function-details (meta (rand-nth function-list))] 34 | (str (function-details :ns) "/" (function-details :name) 35 | "\n " (function-details :arglists) 36 | "\n " (function-details :doc)))) 37 | 38 | 39 | (defn -main 40 | "Return a random function and its details 41 | from the available namespaces" 42 | [& args] 43 | (if (seq args) 44 | (println (random-function (selective-namespace-functions args))) 45 | (println (random-function all-public-functions)))) 46 | 47 | 48 | ;; REPL experiments 49 | ;; 50 | 51 | (comment 52 | 53 | ;; A hash-map of functions in clojure.core 54 | (ns-publics 'clojure.core) 55 | 56 | ;; a sequence of function vars from clojure.core 57 | (vals (ns-publics 'clojure.core)) 58 | 59 | ;; random var from the sequence 60 | (rand-nth (vals (ns-publics 'clojure.core))) 61 | 62 | ;; metadata from a function var 63 | (meta #'map) 64 | ;; => {:added "1.0", 65 | ;; :ns #namespace[clojure.core], 66 | ;; :name map, 67 | ;; :file "clojure/core.clj", 68 | ;; :static true, 69 | ;; :column 1, 70 | ;; :line 2727, 71 | ;; :arglists ([f] [f coll] [f c1 c2] [f c1 c2 c3] [f c1 c2 c3 & colls]), 72 | ;; :doc 73 | ;; "Returns a lazy sequence consisting of the result of applying f to\n the set of first items of each coll, followed by applying f to the\n set of second items in each coll, until any one of the colls is\n exhausted. Any remaining items in other colls are ignored. Function\n f should accept number-of-colls arguments. Returns a transducer when\n no collection is provided."} 74 | 75 | 76 | (meta (rand-nth (vals (ns-publics 'clojure.core)))) 77 | 78 | ;; Get all namespaces from the current classpath 79 | (all-ns) 80 | 81 | (require '[clojure.inspector :as inspector]) 82 | (inspector/inspect-tree (all-ns)) 83 | 84 | 85 | 86 | (mapcat function-list ['clojure.core]) 87 | 88 | (mapcat #(function-list (symbol %)) ['clojure.core]) 89 | (mapcat #(function-list (symbol %)) ["clojure.core"]) 90 | 91 | (mapcat function-list ['clojure.core 'clojure.string]) 92 | 93 | 94 | (ns-publics (var map)) 95 | 96 | (symbol 'clojure.core) 97 | 98 | (function-list 'clojure.core) 99 | 100 | (-main "clojure.string") 101 | 102 | 103 | 104 | ;; call main without arguments uses Clojure standard library 105 | ;; plus any other namespaces in the REPL 106 | (-main) 107 | 108 | ;; calling with a specific namespace will return functions only from that namespace 109 | ;; strings 110 | (-main "clojure.string") 111 | 112 | ) 113 | --------------------------------------------------------------------------------