Skip to content

jessesherlock/zing

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

3 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

Zing

A zipper library with extra implementations for useful data structures (mixed edn collections, hiccup, other map structures as well as the normal seq/vector/xml.parse maps). It also has more regular nil usage and functionality for searching and “marking” nodes to find later.

Install

com.jessesherlock/zing {:mvn/version "0.1.0"} / [com.jessesherlock/zing "0.1.0"]

Basic Zipper operations

Zing has the standard zipper fns from clojure.zip except that the end isn’t detected by an end? fn as nil is returned when navigating past the end, to match the result when navigating outside the zipper going up, left or right.

There are a few useful additions, such as next-leaf and root-loc that are missing from clojure.zip.

Find/Search

Given a predicate and a zipper loc find scans forward until the predicate matches a loc, search returns a vector of matching locs. reverse-find and reverse-search scan backwards. loc-pred turns a node predicate into a loc predicate.

Mark and Rebound

When editing with a zipper it can be useful to mark locations in order to return to them later. mark-loc edits a loc to “mark” it, with and optional label argument.

Rebound marks the current location, scans forward until a predicate is matched, edits the matching location with the provided function, returns to the original location and removes the mark.

(-> [:a [:b :c] :d [:e [:f [:g :h]] :i]]
    ;; nav to :b
    down right down
    ;; find :g, replace with :X and return to :b
    (rebound (loc-pred #(= :g %)) #(replace % :X))
    ;; we're back at :b so go up to root
    up up
    node)
[:a [:b :c] :d [:e [:f [:X :h]] :i]]

Defined Zippers

The standard clojure.zip seq-zip, vector-zip and xml-zip are included as well as a more general tree format, tree-zip (a map with with :label and :children keys for branches), edn-zip for collections of mixed lists, vectors, sets and maps and hiccup-zip for hiccup data.

Defining a new zipper

Uses the standard branch?/children/make-node fns in the zing.zip/Zipper protocol, although they take a loc as an argument instead of a node as the other zipper libraries do. Also the make-node function always takes 3 args. A default implementation of the protocol is supplied for plain maps.

Either define a record with node and path fields or use a regular map like so:

;; vector-zip implemented as a regular map
{:node [:a [:b :c] :d [[:e] :f]]
 :path nil
 :zing.zip/branch? (comp vector? sut/node)
 :zing.zip/children (comp seq sut/node)
 :zing.zip/make-node (fn [this loc children] (vec children))}

About

A Clojure/Clojurescript Zipper library

Resources

Stars

Watchers

Forks

Packages

 
 
 

Contributors