{"id":23168589,"url":"https://github.com/abhinavomprakash/snitch","last_synced_at":"2025-05-16T06:07:59.643Z","repository":{"id":44330375,"uuid":"455765604","full_name":"AbhinavOmprakash/snitch","owner":"AbhinavOmprakash","description":"    Snitch injects inline defs in your functions and multimethods. This enables a repl-based, editor-agnostic, clojure and clojurescript debugging workflow. It is inline-defs on steroids.","archived":false,"fork":false,"pushed_at":"2025-04-15T13:12:21.000Z","size":222,"stargazers_count":190,"open_issues_count":17,"forks_count":4,"subscribers_count":4,"default_branch":"main","last_synced_at":"2025-05-16T06:07:49.046Z","etag":null,"topics":["clojure","clojure-script"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/AbhinavOmprakash.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2022-02-05T03:32:36.000Z","updated_at":"2025-05-16T01:27:10.000Z","dependencies_parsed_at":"2024-09-12T17:18:47.051Z","dependency_job_id":"89f58868-1635-4eaa-8f97-24043182c1ce","html_url":"https://github.com/AbhinavOmprakash/snitch","commit_stats":{"total_commits":88,"total_committers":2,"mean_commits":44.0,"dds":"0.045454545454545414","last_synced_commit":"6952f15100e8770c7750bb4370c895a475b6559e"},"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbhinavOmprakash%2Fsnitch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbhinavOmprakash%2Fsnitch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbhinavOmprakash%2Fsnitch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/AbhinavOmprakash%2Fsnitch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/AbhinavOmprakash","download_url":"https://codeload.github.com/AbhinavOmprakash/snitch/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254478193,"owners_count":22077676,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["clojure","clojure-script"],"created_at":"2024-12-18T03:11:55.948Z","updated_at":"2025-05-16T06:07:54.547Z","avatar_url":"https://github.com/AbhinavOmprakash.png","language":"Clojure","funding_links":[],"categories":[],"sub_categories":[],"readme":"# snitch\n\n[![Clojars Project](https://img.shields.io/clojars/v/org.clojars.abhinav/snitch.svg)](https://clojars.org/org.clojars.abhinav/snitch)\n\n\u003e Snitch is inline-defs on steroids\n\n\nSnitch is how I debug and understand data flowing through my system.\nIt's not a replacement for a full-fledged debugger, but it's pretty close and will be useful in 90% of the cases. \nI use it as my sole debugger (in rare cases I reach for print statements). \n\n# Features \n- Support for Clojurescript. \n- Editor agnostic (use it along with cider, conjure, calva, or cursive!).\n- Highly ergonomic for repl-driven development.\n\n# What people have to say ❤️ \n\u003e Very handy with those variants of the regular macros. Just add a `*` and you are inline def-ing the args! - Peter Strömberg (co-author of Calva)\n\n# Talk\nI gave a [talk](https://www.youtube.com/watch?v=WqilQulsJQc) about snitch at clojure Asia you can watch it \nhere https://www.youtube.com/watch?v=WqilQulsJQc.\n\n# Usage\n## Installation\nI recommend adding snitch to your `~/.lein/profiles.clj`.\nAn example file would be\n```clojure\n; profiles.clj\n{:user {:dependencies [[org.clojars.abhinav/snitch \"0.1.16\"]]}}\n\n{:dev {:dependencies [[org.clojars.abhinav/snitch \"0.1.16\"]]}}\n```\nIf you add it to your project's dev dependencies, you could add this line to your dev/user.clj\n```\n(require '[snitch.core :refer [defn* defmethod* *fn *let]])\n```\nrequiring these macros once, will intern these macros inside clojure.core \u0026 cljs.core, so you don't have to import them in every namespace.\n\n## Overview\nThere are four macros `defn*`, `defmethod*` `*fn`, `*let`.\nThey are drop-in replacements for `defn`, `defmethod`, `fn`, and `let`.\n\nThese macros creates inline defs of the parameters passed to the functions,\nand also inside the let bindings of the functions.\nThis makes it very \"ergonomic\" for repl-driven development.\n\n## defn*\n\ndefn* walks your clojure form and injects inline defs for all the bindings in the form.\nThis includes the arguments as well as bindings inside a let body, and any lambda function. \n\n```clojure\n(require '[snitch.core :refer [defn*]])\n\n\n(defn* foo [a b]\n  (+ a b)\n  nil)\n\n;;  calling foo with random integers\n(foo (rand-int 100) (rand-int 100)) ; nil\n\n\n;; we can evaluate the value of a and b\na ; 15\n\nb ; 85\n\n\n;; we can get the return value of foo by appending a \u003c to foo\n\nfoo\u003c \n=\u003e nil\n\n;; it roughly expands to a form that looks like this. \n;; the actual macro expansion is more complex.\n(clojure.core/defn\n   foo\n   [a b]\n   (def a a)\n   (def b b)\n   (clojure.core/let\n    [result__12589__auto__ (do (+ a b) nil)]\n    (def foo\u003c result__12589__auto__)\n    result__12589__auto__))\n```\n\nA more complex example\n\n```clojure\n(require '[snitch.core :refer [defn*]])\n\n(defn* foo1 [{:keys [a/b1 c2]\n                dee3 :d3\n                :as m4}\n               [x5 [y6 [z7]]]]\n    [b1 c2 dee3 m4 x5 y6 z7])\n\n;; there is some crazy destructuring going on in the function parameters.    \n;; snitch handles this with ease\n\n(foo1 {:a/b1 1 :c2 2 :d3 3 :e 100 :f 200}\n      [5 [6 [7]]]) \n;=\u003e [1 2 3 {:a/b1 1, :c2 2, :d3 3} 5 6 7]\n\n;; we can evaluate each var.\n\nb1 ; 1\ndee3 ; 3\nm4 ; {:a/b1 1, :c2 2, :d3 3}\nz7 ; 7\n\nfoo1\u003c ; [1 2 3 {:a/b1 1, :c2 2, :d3 3} 5 6 7]\n\n;; now for the coolest feature (IMO).\n;; imagine a case where foo1 was called in some namespace ( you don't really know what was passed to it)\n;; but there is a bug in foo1 that you want to fix\n;; how do you reconstruct the function call?\n;; we have the parameters defined, but you can't do this\n\n(foo1 b1 dee3....)\n;; because it needs to be passed a map and a vector. \n;; constructing the map is very painful and time consuming.\n;; snitch provides functionality for that too.\n;; just evaluate foo1\u003e \n\nfoo1\u003e ; (foo1 {:a/b1 1, :c2 2, :d3 3} [5 [6 [7]]])\n\n;; foo1\u003e returns a list that can be evaluated \n;; notice that when snitch reconstructed the function call, \n;; it left out the keys :e and :f? \n;; the original map passed was {:a/b1 1 :c2 2 :d3 3 :e 100 :f 200}\n\n;; snitch is smart that way and only constructs the arguments absolutely necessary \n;; for the function call. \n```\n\ninjecting inline defs inside let forms\n```clojure\n(defn* foobar []\n  (let [a 1] a))\n\n(foobar) ; 1\na ; 1\n\n```\n\ninjecting inline defs inside lambda forms\n```clojure\n(defn* foobar [a]\n  ((fn [b] b) a))\n\n(foobar 4) ; 1\na ; 4\nb ; 4\n```\n\n## *let \n*let will recursively inject inline defs for the all binding forms including any lambda forms.\n```clojure\n(*let [a 1]\n      (let [b 2]   ; this isn't a *let but the top-level *let injects inline defs for this as well\n        (let [c 3] ; and for this too!\n          [a b c])))\n\na ; 1\nb ; 2\nc ; 3\n```\n\n## *fn \nSimilar to `defn*`, will consider the name of the lambda function as `this` if not provided.\n\n```clojure\n((*fn [a]\n      (let [b :b]\n        [a b]))\n :a)  ; [:a :b]\na ; :a\nb ; :b\nthis\u003c ; [:a :b]\n```\n\n# Clojurescript support\n\nSnitch works with clojurescript as well.\n\n## shadow-cljs.edn\nyou can add the dependency to `~/.shadow-cljs/config.edn`. \n```clojure\n{:dependencies \n [[org.clojars.abhinav/snitch \"0.1.16\"]]}\n```\nThe import for clojurescript looks different. \n\n```clojure\n(:require [snitch.core :refer-macros [defn*]])\n```\n\n# Integrating snitch in your workflow.\n\nI have two vim macros that inject `(require '[snitch.core :refer [defn* defmethod* *fn *let]])` at the top of my ns, and evaluate it.\n\n\n```vimrc\n\"for clj\nlet @s = \"m8gg0)o(require 'jkf'xi[snitch.core :refer [defn* defmethod* *fn *let]])jk;ee`8\"\n\n\"for cljs\nlet @n = \"m8gg0\u003eI(:require [snitch.core :refer-macros [defn* defmethod* *fn *let]])jk;er`8\"\n```\nthe macro does the following things.\n1. mark the current position.\n2. go to the start of the file.\n3. go to the end of the top-level s-exp (ns-form).\n4. insert newline and add the require.\n5. evaluate it using `;ee` (conjure's evaluation command)\n6. go back to the marked position.\n\nthe macro is specific to my config, but the steps will give you an idea to create your own macros.\n\nif you have created any specific macros/workflows for your editor of choice, you can open a PR and add it to the readme :)\n\n\n# License \nParts of the code in snitch is taken from clojure.core and cljs.core.\n\n```\n *   Copyright (c) Rich Hickey, Abhinav Omprakash. All rights reserved.\n *   The use and distribution terms for this software are covered by the\n *   Eclipse Public License 1.0 (http://opensource.org/licenses/eclipse-1.0.php)\n *   which can be found in the file license.md at the root of this distribution.\n *   By using this software in any fashion, you are agreeing to be bound by\n * \t the terms of this license.\n *   You must not remove this notice, or any other, from this software.\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhinavomprakash%2Fsnitch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fabhinavomprakash%2Fsnitch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fabhinavomprakash%2Fsnitch/lists"}