{"id":13396423,"url":"https://github.com/athos/Pinpointer","last_synced_at":"2025-03-13T23:30:59.288Z","repository":{"id":62434230,"uuid":"63513952","full_name":"athos/Pinpointer","owner":"athos","description":"Pinpointer is yet another clojure.spec error reporter based on a precise error analysis","archived":false,"fork":false,"pushed_at":"2019-08-10T05:34:12.000Z","size":510,"stargazers_count":94,"open_issues_count":6,"forks_count":3,"subscribers_count":8,"default_branch":"master","last_synced_at":"2024-09-19T05:21:59.498Z","etag":null,"topics":["clojure","clojure-spec","clojurescript","error-messages","spec"],"latest_commit_sha":null,"homepage":"","language":"Clojure","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"epl-1.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/athos.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}},"created_at":"2016-07-17T04:01:54.000Z","updated_at":"2024-05-31T07:47:54.000Z","dependencies_parsed_at":"2022-11-01T21:02:10.872Z","dependency_job_id":null,"html_url":"https://github.com/athos/Pinpointer","commit_stats":null,"previous_names":[],"tags_count":2,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/athos%2FPinpointer","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/athos%2FPinpointer/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/athos%2FPinpointer/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/athos%2FPinpointer/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/athos","download_url":"https://codeload.github.com/athos/Pinpointer/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":243499899,"owners_count":20300711,"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-spec","clojurescript","error-messages","spec"],"created_at":"2024-07-30T18:00:50.905Z","updated_at":"2025-03-13T23:30:58.964Z","avatar_url":"https://github.com/athos.png","language":"Clojure","funding_links":[],"categories":["Better Error Output"],"sub_categories":[],"readme":"# Pinpointer\n[![Clojars Project](https://img.shields.io/clojars/v/pinpointer.svg)](https://clojars.org/pinpointer)\n[![CircleCI](https://circleci.com/gh/athos/Pinpointer/tree/master.svg?style=shield)](https://circleci.com/gh/athos/Pinpointer/tree/master)\n[![codecov](https://codecov.io/gh/athos/Pinpointer/branch/master/graph/badge.svg)](https://codecov.io/gh/athos/Pinpointer)\n[![join the chat at https://gitter.im/athos/pinpointer](https://badges.gitter.im/athos/pinpointer.svg)](https://gitter.im/athos/pinpointer?utm_source=badge\u0026utm_medium=badge\u0026utm_campaign=pr-badge\u0026utm_content=badge)\n\nPinpointer is yet another clojure.spec error reporter based on a precise error analysis.\n\nIt has the following features:\n\n- Visually pinpoints which portion of the input data is causing the spec error, based on the spec error analysis of [`spectrace`](https://github.com/athos/spectrace), a fine-grained spec error analyzer\n- Formats and colorizes the error reports in an easy-to-grasp manner\n- Tracks 'value changes', i.e. reports the spec errors correctly even when `s/conformer` in the spec transforms the input data\n- Extensible to user-defined spec macros (not documented yet)\n\n**Notice**: Pinpointer is built on top of clojure.spec, which is one of Clojure's new features that have been developed most actively. So, it's still in alpha and its APIs are also subject to change.\n\n## Installation\n\nAdd the following to your `:dependencies`:\n\n[![Clojars Project](https://clojars.org/pinpointer/latest-version.svg)](http://clojars.org/pinpointer)\n\n## Why and how to use it\n\nclojure.spec provides an API named `explain`, which describes which portion of the input data caused a spec error:\n\n```clj\n=\u003e (s/def ::x integer?)\n:user/x\n=\u003e (s/def ::y string?)\n:user/y\n=\u003e (s/explain (s/keys :req-un [::x ::y]) {:y 1})\nIn: [:y] val: 1 fails spec: :user/y at: [:y] predicate: string?\nval: {:y 1} fails predicate: (contains? % :x)\nnil\n=\u003e\n```\n\nAs you can see above, the result of `explain` is simple and plain, but it is often not easy to understand intuitively what was wrong. And it will take longer time to find out where the actual problem is as the spec and input data are getting larger.\n\n### pinpoint: replacement of s/explain\n\n_Pinpointer_ provides an API compatible with `explain`, which is named `pinpoint`, and it shows the spec errors in a visually  easy-to-grasp manner:\n\n```clj\n=\u003e (require '[pinpointer.core :as p])\nnil\n=\u003e (p/pinpoint (s/keys :req-un [::x ::y]) {:y 1})\nDetected 2 spec errors:\n----------------------------------------------------------------------\n(1/2)\n\n    Cause: {:y 1}\n           ^^^^^^\n Expected: (fn [%] (contains? % :x))\n\n----------------------------------------------------------------------\n(2/2)\n\n    Cause: {:y 1}\n               ^\n Expected: string?\n\n----------------------------------------------------------------------\nnil\n=\u003e\n```\n\n\nYou can also colorize the error reports by adding the option `{:colorize :ansi}` to increase the readability:\n\n\n\u003cimg src=\"doc/images/colorized-pinpoint-result.png\" width=\"630\"\u003e\n\n`pinpoint` has several other options. See the docstring for more details.\n\n### pinpoint-out: plugin implementation for s/\\*explain-out\\*\n\nIf you'd rather completely replace the `explain` facility for any kinds of spec error reporting, it would be helpful to replace `s/*explain-out*` with `pinpointer.core/pinpoint-out` instead:\n\n```clj\n=\u003e (set! s/*explain-out* p/pinpoint-out)\n#function[pinpointer.core/pinpoint-out]\n=\u003e\n;; from now on, p/pinpoint-out will be used in place of s/explain-printer\n=\u003e\n=\u003e (defn f [x] (inc x))\n#'user/f\n=\u003e (s/fdef f\n     :args (s/cat :x (s/and integer? even?))\n     :ret (s/and integer? odd?))\nuser/f\n=\u003e (require '[clojure.spec.test.alpha :as t])\nnil\n=\u003e (t/instrument)\n[user/f]\n=\u003e (f 3)\nExceptionInfo Call to #'user/f did not conform to spec:\nDetected 1 spec error:\n----------------------------------------------------------------------\n(1/1)\n\n    Cause: (3)\n            ^\n Expected: even?\n\n----------------------------------------------------------------------\n  user/eval3842 (form-init1169392389971828339.clj:1)\n  clojure.core/ex-info (core.clj:4744)\n=\u003e\n```\n\n## ClojureScript support\n\nPinpointer also supports ClojureScript. Note, however, that it may use `eval` for its spec error analysis in general (especially, when analyzing specs with a literal fn in them) while ClojureScript doesn't have a platform-independent `eval` fn.\n\nIf you use Pinpointer from a self-hosted ClojureScript implementation equipped with `eval` such as Planck or Lumo, it should work fine even in general cases as follows:\n\n```clj\n=\u003e (require '[planck.core :as planck])\nnil\n=\u003e (p/pinpoint (s/and integer? #(\u003e % 10)) 5 {:eval planck/eval})\nDetected 1 spec error:\n----------------------------------------------------------------------\n(1/1)\n\n    Cause: 5\n           ^\n Expected: (fn [%] (\u003e % 10))\n\n----------------------------------------------------------------------\nnil\n=\u003e\n```\n\n## Known Issues\n\nThere are a couple of known issues in Pinpointer, primarily due to `clojure.spec`'s bugs. They can be found on [Issues page](https://github.com/athos/Pinpointer/issues?q=is%3Aissue+is%3Aopen+label%3A%22spec+bug%22), being tagged with `spec bug`.\n\nIf you found something wrong when using Pinpointer and you want to report an issue, check whether or not it's already been filed there first.\n\n## License\n\nCopyright © 2016-2018 Shogo Ohta ([@athos0220](https://twitter.com/athos0220))\n\nDistributed under the Eclipse Public License 1.0.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fathos%2FPinpointer","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fathos%2FPinpointer","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fathos%2FPinpointer/lists"}