-
-
Save danieroux/dfb277f47b74fc61c87a92d47edd8c5a to your computer and use it in GitHub Desktop.
Monkey patching clojure.core for dev convenience
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
;; Load this in user.clj with: | |
; (load "monkey_patch_clojure_core") | |
(ns monkey-patch-clojure-core | |
(:require | |
[taoensso.timbre :as log])) | |
(log/info "Monkey patching clojure.core, adding:") | |
(log/info (str " " 'ddef)) | |
(log/info (str " " 'unddef)) | |
(log/info (str " " 'profile)) | |
(log/info (str " " 'gen-one)) | |
(log/info (str " " 'gen-sample)) | |
(log/info (str " " 'pbcopy)) | |
(log/info (str " " 'pbcopy-pr)) | |
(ns clojure.core) | |
(defmacro ddef | |
"Sugar: | |
(ddef x y z) -> (def x x) (def y y) (def x x)" | |
[& names] | |
(cons | |
'do | |
(map | |
(fn [n] | |
`(def ~n ~n)) | |
names))) | |
(defmacro unddef | |
[& names] | |
(cons | |
'do | |
(map | |
(fn [n] | |
`(ns-unmap *ns* (quote ~n))) | |
names))) | |
(require '[clj-async-profiler.core]) | |
(defmacro profile | |
"Profile the execution of `body`. If the first argument is a map, treat it as | |
options. For available options, see `start` and `stop`. `:pid` option is | |
ignored, current process is always profiled. Additional options: | |
:return-file - if true, return the generated flamegraph file, otherwise return | |
the value returned by `body` (default: false - return value)" | |
{:matter.dev/copied-from "https://github.com/clojure-goes-fast/clj-async-profiler/blob/master/src/clj_async_profiler/core.clj#L349" | |
:matter.dev/why "Easy profiling. Open the file profile.clj and load it, after you profiled"} | |
[options? & body] | |
(let [[options body] (if (map? options?) | |
[(dissoc options? :pid) body] | |
[{} (cons options? body)])] | |
`(let [options# ~options | |
_# (println (clj-async-profiler.core/start options#)) | |
f# (atom nil) | |
ret# (try ~@body | |
(finally (reset! f# (clj-async-profiler.core/stop options#))))] | |
(if (:return-file options#) | |
@f# ret#)))) | |
(defn gen-one | |
"Gen one of the given spec, setting recursion limit. | |
Override recursion limit with :recursion-limit" | |
[spec & {:keys [recursion-limit] | |
:or {recursion-limit 1}}] | |
(require 'clojure.spec.alpha) | |
(require 'clojure.spec.gen.alpha) | |
(binding [clojure.spec.alpha/*recursion-limit* recursion-limit] | |
(clojure.spec.gen.alpha/generate (clojure.spec.alpha/gen spec)))) | |
(defn gen-sample | |
"Gen a sample of the given spec, setting recursion limit. | |
Override size with :sample-size. | |
Override recursion limit with :recursion-limit" | |
[spec & {:keys [sample-size recursion-limit] | |
:or {sample-size 10 | |
recursion-limit 1}}] | |
(require 'clojure.spec.alpha) | |
(require 'clojure.spec.gen.alpha) | |
(binding [clojure.spec.alpha/*recursion-limit* recursion-limit] | |
(clojure.spec.gen.alpha/sample | |
(clojure.spec.alpha/gen spec) | |
sample-size))) | |
(defmacro pbcopy | |
"OSX Super convenience: The result of form will be in the OSX paste buffer. | |
Assumes string." | |
[& body] | |
`(clojure.java.shell/sh "pbcopy" :in ~@body)) | |
(defmacro pbcopy-pr | |
"OSX Super convenience: The result of form will be in the OSX paste buffer, after pr-str | |
A cleverer thing can happen here: `:in` could be `*out*`. Later." | |
[& body] | |
`(clojure.java.shell/sh "pbcopy" :in (pr-str ~@body))) | |
(comment | |
(pbcopy "Hello pbcopy") | |
(macroexpand-1 `(pbcopy-pr (hash-map :a 5))) | |
(pbcopy-pr (hash-map :a 5)) | |
(pbcopy-pr {:a 5}) | |
()) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment