A release with known breaking changes is marked with:
-
[breaking] you probably need to change your code
-
[minor breaking] you likely don’t need to change your code
-
fix: Don’t crash when 1-char buffer PBR is provided. #466 (@alexander-yakushev)
-
perf: Add fastpaths to rewrite-clj.node.stringz/sexpr #458 (@alexander-yakushev)
-
perf: Optimize parse-token #459 (@alexander-yakushev)
-
perf: Reuse common whitespace and newline nodes #460 (@alexander-yakushev)
-
perf: Simplify NewlineNormalizingReader #461 (@alexander-yakushev)
-
perf: pass explicit context instead delimiter dynvar. #442 (@alexander-yakushev)
-
perf: Use more efficient StringBuilder.append arity #443 (@alexander-yakushev)
-
perf: Reader optimizations #444 (@alexander-yakushev)
-
coerceallISeqs to lists (instead of handful of specific seqs) #435 (@lread, thanks for the issue @shaunlebron!)
-
rewrite-clj.zip/insert-rightandrewrite-clj.zip/append-childno longer insert a space when inserting/appending after a comment node. #346 (@lread) -
bump
clojure/tools.readerto correct:end-colmetadata for keywords at end of content #367 (@lread) -
rewrite.clj.paredit-
now supports paredit ops on new/changed nodes in a zipper #256 (@lread, thanks for the issue mrkam2!)
-
posarguments now accept vector[row col]in addition to map{:row :col}#344 (@lread) -
joinnow takes type of left sequence #321 (@lread, thanks for the issue @openvest!) -
joinno longer removes comments that were between joined strings #351 (@lread) -
split-at-posno longer throws on split at string opening quote #350 (@lread) -
kill-one-at-posword deletion in string/comment off-by-one error fixed #343 (@lread) -
Address design flaw of
slurpfunctionsDeprecated Replacement slurp-forwardslurp-forward-intoslurp-forward-fullyslurp-forward-fully-intoslurp-backwardslurp-backward-intoslurp-backward-fullyslurp-backward-fully-into -
stop adding space char when preserving slurped newlines #345 (@lread)
-
when slurping don’t consider a node with
#_ unevalnodes empty #338 (@lread) -
when slurping don’t throw on rewrite-clj parseable, but invalid clojure, i.e.,
{:a}#336 (@lread) -
slurping forward fully no longer throws when slurping into an empty seq that is the last item in a seq #335 (@lread)
-
slurping backward at empty-seq at start of a seq no longer throws #334 (@lread)
-
slurping forward now slurps when at empty seq at end of a seq #333 (@lread)
-
when
posis at closing",)], etckill-at-pos,kill-one-at-posnow kill the found node #362 (@lread)
-
-
bump
org.clojure/tools.readerto version1.5.0(@lread) -
sexprnow better matches clojureread-stringfor~,@and~@#305 (@frenchy64)
-
bump
org.clojure/tools.readerto version1.4.2(@lread) -
sexprnow 1) expands tag metadata to its long form 2) throws on invalid metadata #280 (@lread) -
Add support for Clojure 1.12 vector metadata (ex.
(^[double] String/valueOf 3)) #279 (@lread) -
Add support for Clojure 1.12 array class syntax (ex.
byte/3) #279 (@lread) -
rewrite-clj.paredit/barf-forwardon zipper created with:track-position? truenow correctly barfs when current node has children #245 (@lread, thanks for the issue @p4ulcristian!) -
docs
-
added new
rewrite-clj.zipfunctionsof-string*andof-file*, these are versions ofof-stringandof-filethat do no auto-navigation #189 (@lread, thanks @mainej for the analysis work!) -
a lazy sequence now coerces to a rewrite-clj list node #180 (thanks @borkdude!)
-
exceptions thrown while reading now include
:rowand:colkeys inex-data#181 (thanks @ferdinand-beyer) -
docs
-
a docstring typo fix #191 (thanks @bobbicodes!)
-
-
dropped the alpha status (@lread)
-
changed rewrite-clj library version scheme from commit-count to release-num #179 (@lread)
-
renamed zipper creation functions that take a rewrite-clj node as input. The old names did not reflect their purpose which led to confusion. Old functions will remain but are marked as deprecated. #178 (@lread)
-
rewrite-clj.zip/edn→rewrite-clj.zip/of-node -
rewrite-clj.zip/edn*→rewrite-clj.zip/of-node*
-
-
now properly escaping inline double quotes for coerced strings #176 (@lread, thanks to @ivarref for raising the issue!
-
docs:
-
docstring fix, was missing
list-nodefrom toc (thanks @rfhayashi!)
-
-
update clojure tools.reader dependency to v1.3.6 (@lread)
-
a zipper created with both a custom
:auto-resolveoption and the:track-position?trueoption will now acknowledge and use the custom:auto-resolve#159 (@lread) -
a Cons now coerces to a rewrite-clj list node #160 #161 (thanks @borkdude!)
-
internal rewrite-clj developer facing:
-
user guide and docstrings better explain
sexpr-able?and what invalid code elements rewrite-clj parses #150 #151 (@lread) -
rewrite-clj now exports clj-kondo config for its public API #146 (@lread)
-
ClojureScript compiler should no longer emit invalid deprecated warnings #153 (@lread)
-
Internal rewrite-clj developer facing:
-
Switched from babashka scripts to babashka tasks, developer guide updated accordingly (@lread)
-
If you wish, you can read nitty gritty details on merging rewrite clj v0 and rewrite cljs. What follows is a summary of changes.
-
Minimum Clojure version bumped from v1.5.1 to v1.9
-
Minimum ClojureScript version (from whatever is was for rewrite-cljs) bumped to v1.10
-
Minimum Java version bumped from v7 to v8
-
Keyword node field
namespaced?renamed toauto-resolved? -
Now using
ex-infofor explicitly raised exceptions -
Rewrite-cljs positional support migrated to rewrite-clj’s positional support
-
Namespaced element support reworked
-
v1 changes do not affect node traversal of the namespaced map, number and order of children remain the same.
-
Namespace map prefix, is now stored in a namespaced map qualifier node.
-
Prior to v1, the prefix was parsed to a keyword-node.
-
Let’s look at what interesting node API functions will return for the prefix node in the following namespaced maps. Assume we have parsed the example and traversed down to the prefix node.
For example via:(→ "#:prefix{:a 1}" z/of-string z/down z/node).node API call rewrite-clj #:prefix{:a 1}#::alias{:a 1}#::{:a 1}string
is unchangedv1
":prefix""::alias""::"v0
-
throws on parse
tag
is differentv1
:map-qualifierv0
:token-
throws on parse
inner?
still indicates that the node is a leaf node and has no childrenv1
falsev0
false-
throws on parse
sexpr<read on below for discussion on sexpr>
-
-
-
Namespaced element
sexprsupport now relies on user specifiable auto-resolve function to resolve qualifiers-
Unlike rewrite-clj v0, the default auto-resolve behaviour never consults
*ns* -
An sexpr for keyword node
::alias/foono longer returns:alias/foo(this could be considered a bug fix, but if your code is expecting this, then you’ll need to make changes)
-
-
The following namespaced element
sexprexamples assume:-
*ns*is bound tousernamespace (important only for rewrite-clj v0): -
We are using the default auto-resolve function for rewrite-clj v1
-
That you will refer to the User Guide for more detailed examples of v1 behaviour
source sexpr rewrite-clj v1 sexpr rewrite-clj v0 sexpr rewrite-cljs qualified keyword
:prefix/foono change
current-ns qualified keyword
::foo:?_current-ns_?/foo:user/foo-
throws on sexpr
ns-alias qualified keyword
::alias/foo:??_alias_??/foo:alias/foo:alias/fooqualified map
#:prefix{:a 1}#:prefix{:a 1}#:prefix{:a 1}(read-string "#:prefix{:a 1}")current-ns qualified map
#::{:b 2}#:?_current-ns_?{:b 2}-
throws on parse
-
throws on parse
ns-alias qualified map
#::alias{:c 3}#:??_alias_??{:c 3}-
throws unless namespace alias
aliashas been loaded in*ns* -
if
aliasinnsresolves tomy.ns1:
#:my.ns1{:c 3}
(read-string "#::alias{:c 3}") -
-
Let’s dig into prefix and key sub-nodes of a namespaced map to explore v1 differences:
Description rewrite-clj v1 rewrite-clj v0 and rewrite-cljs prefix (aka qualifier)
qualified
(-> "#:prefix{:a 1}" z/of-string z/down z/sexpr)
prefix:prefixcurrent-ns qualified
(-> "#::{:b 2}" z/of-string z/down z/sexpr)
?_current-ns_?-
throws on parse
ns-alias qualified
(-> "#::alias{:c 2}" z/of-string z/down z/sexpr)
??_alias_??:user/alias-
rewrite-cljs throws
key
qualified
(-> "#:prefix{:a 1}" z/of-string z/down z/right z/down z/sexpr)
:prefix/a:acurrent-ns qualified
(-> "#::{:b 2}" z/of-string z/down z/right z/down z/sexpr)
:?current-ns?/b-
throws on parse
ns-alias qualified
(-> "#::alias{:c 3}" z/of-string z/down z/right z/down z/sexpr)
:??_alias_??/c:c -
-
-
-
Potentially breaking
-
Some rewrite-cljs optimizations were dropped in favor of a single code base. If performance for rewrite-clj v1 for ClojureScript users is poor with today’s ClojureScript, we shall adapt.
-
Deleted redundant
rewrite-clj.parser.util#93 (@lread). If you were using this internal namespace you can opt to switch to, the also internal,rewrite-clj.readernamespace.
-
-
A new home under clj-commons. Thanks to @xsc, rewrite-clj will also retain its same maven coordinates on Clojars making for a seamless upgrade path for rewrite-clj v0 users.
-
Now supports ClojureScript, merging in rewrite-cljs specific functionality. Frustrations like not having namespace map support and differences from rewrite-clj, like whitespace parsing, should now be things of the past. Rewrite-cljs users migrating to rewrite-clj v1 are now at, and will remain at, feature parity with rewrite-clj.
-
Additions to the public API:
-
rewrite-clj.paredit- carried over from rewrite-cljs, an API for structured editing of Clojure forms -
rewrite-clj.zip-
Exposes the following (accidentally?) omitted functions:
-
append-child* -
insert-newline-left -
insert-newline-right -
insert-space-left -
insert-space-right -
subzip
-
-
Adds functions from rewrite-cljs
-
find-last-by-pos- navigate to node at row/col -
find-tag-by-pos- navigate to node with tag at row/col -
position-span- returns start and end row/col for a form -
remove-preserve-newline- same as remove but preserves newlines
-
-
Adds namespaced element support functions
-
reapply-context- reapplies (or removes) map qualifier node context from keywords and symbols -
zipper creation functions now optionally accept an auto-resolve function to support sexpr on namespaced element nodes
-
-
Other additions
-
sexpr-able?- return true ifsexpris supported for current node
-
-
-
rewrite-clj.node-
Additions:
-
keyword-node?- returns true if form is a rewrite-clj keyword node -
map-qualifier-node- to create a namespaced map’s map qualifier node manually -
map-context-apply- apply map qualifier to keyword or symbol -
map-context-clear- remove map qualifier from keyword or symbol -
node?- returns true if a form is a rewrite-clj created node -
sexpr-able?- return true ifsexpris supported for node -
symbol-node?- return true if node is a rewrite-clj symbol node
-
-
Updates:
-
sexpr,sepxrsandchild-sexprs- now optionally take an options argument to specify an auto-resolve function
-
-
-
-
Many updates to docs and docstrings
-
OS specific end of line variants in source now normalized consistently to
\newline#93 (@lread) -
Postwalk on larger source file no longer throws StackOverflow #69 (@lread)
-
Correct and document prefix and suffix functions #91 (@lread)
-
Positional metadata added by the reader is elided on coercion #90 (@lread)
-
Ensure that all rewrite-clj nodes coerce to themselves (@lread)
-
Strings now coerce to string nodes (instead of to token nodes) #126 (@lread)
-
Regex node now:
-
Moved from potemkin import-vars to static template based version #98 (@lread):
-
Avoids frustration/mysteries of dynamic import-vars for users and maintainers
-
Argument names now correct in API docs (some were gensymed previously)
-
Also turfed use of custom version of potemkin defprotocol+ in favor of plain old defprotocol. Perhaps I missed something, but I did not see the benefit of defprotocol+ for rewrite-clj v1.
-
-
ClojureScript tests, in addition to being run under node, are now also run under chrome-headless, shadow-cljs, and for self-hosted ClojureScript, under planck. (@lread)
-
Now testing rewrite-clj compiled under GraalVM native-image in two variants (@lread):
-
In a pure form where library and tests are compiled
-
Via sci where a sci exposed rewrite-clj is compiled, then tests are interpreted.
-
-
Now automatically testing rewrite-clj against popular libs #124 (@lread)
-
Now linting source with clj-kondo (@lread)
-
Code coverage reports now generated for Clojure unit test run and sent to codecov.io (@lread)
-
Can now preview for cljdoc locally via
script/cljdoc_preview.clj(@lread) -
API diffs for rewrite-clj v1 vs rewrite-clj v0 vs rewrite-cljs can be generated by
script/gen_api_diffs.clj(@lread) -
Contributors are acknowledged in README and updated via
script/update_readme.clj(@lread) -
Doc code blocks are automatically tested via
script/doc_tests.clj#100 (@lread) -
Some tooling and tech replaced (@lread):
-
All scripts are written in Clojure and run via Babashka or Clojure.
-
Switched from leiningen
project.cljto Clojure tools CLIdeps.edn -
Moved from CommonMark to AsciiDoc for docs
-
Moved from publishing docs locally via codox to publishing to cljdoc
-
Now using CommonMark in docstrings (they render nicely in cljdoc)
-
Moved from TravisCI to GitHub Actions where, in addition to Linux, we also test under macOS and Windows
-
Adopted kaocha for Clojure testing, stuck with doo for regular ClojureScript testing, and added support for ClojureScript watch testing with figwheel main.
-
Potemkin dynamic import-vars replaced with static code generation solution
-
-
Added GitHub issue templates (@lread)
-
BREAKING: uses a dedicated node type for regular expressions. #49 (thanks @ChrisBlom)
-
fixes parsing of multi-line regular expressions. #51 (thanks @brian-dawn!)
-
BREAKING: commas will no longer be parsed into
:whitespacenodes but:comma. #44 (thanks @arrdem!) -
BREAKING:
positionwill throw exception if not used on rewrite-clj custom zipper. #45 (@xsc) -
BREAKING: drops testing against JDK6.
-
DEPRECATED:
-
append-spacein favour ofinsert-space-right -
prepend-spacein favour ofinsert-space-left -
append-newlinein favour ofinsert-newline-right -
prepend-newlinein favour ofinsert-newline-left
-
-
fix insertion of nodes in the presence of existing whitespace. #33, 34 (thanks @eraserhd!)
-
ednandedn*now take a:track-position?option that activates a custom zipper implementation allowingpositionto be called on. #41, 45 (thanks @eraserhd!) -
fix serialization of `integer-node`s. #37 (thanks @eraserhd!)
-
adds
insert-left*andinsert-right*to facade.
Development has branched off, using the 0.4.x branch
-
upgrades dependencies.
-
fixes a compatibility issue when running 'benedekfazekas/mranderson' on a project with both 'rewrite-clj' and 'potemkin'.
-
switch to Clojure 1.8.0 as base Clojure dependency; mark as "provided".
-
switch to MIT License.
-
drop support for JDK6.
-
fix
:fnnodes (wereprintable-only?but should actually create an s-sexpression). -
fix
assert-sexpr-countto not actually create the s-expressions.
-
BREAKING
rewrite-clj.zip.indentno longer usable. -
BREAKING node creation/edit has stricter preconditions (e.g.
:metahas to contain exactly two non-whitespace forms). -
BREAKING moved to a type/protocol based implementation of nodes.
-
add node constructor functions.
-
add
child-sexprsfunction.
-
drop tests for Clojure 1.4.0.
-
fix behaviour of
leftmost. -
upgrade to fast-zip 0.5.2.
-
add
:unevalelement type (for#_formelements). -
fix
estimate-lengthfor multi-line strings.
-
upgrade dependencies.
-
fix file parser (UTF-8 characters were not parsed correctly, see #24@xsc/lein-ancient).
-
added token type
:newlineto handle linebreak characters. -
rewrite-clj.zip/ednwraps everything into[:forms …]node, but the initial location is the node passed to it. -
new functions in
rewrite-clj.zip.core:-
length -
move-to-node -
edit→>,edit-node -
subedit→,subedit→>,edit-children -
leftmost?,rightmost?
-
-
new functions in
rewrite-clj.zip.edit:-
splice-or-remove -
prefix,suffix(formerlyrewrite-clj.zip.utils)
-
-
rewrite-clj.zip.edit/removenow handles whitespace appropriately. -
indentation-aware modification functions in
rewrite-clj.zip.indent:-
indent -
indent-children -
replace -
edit -
insert-left -
insert-right -
remove -
splice
-
-
fast-zip utility functions in
rewrite-clj.zip.utils
-
added more expressive error handling to parser.
-
added multi-line string handling (node type:
:multi-line) -
new functions in
rewrite-clj.printer:-
→string -
estimate-length
-
-
new functions in
rewrite-clj.zip:-
of-string,of-file -
print,print-root -
→string,→root-string -
append-space,prepend-space -
append-newline,prepend-newline -
right*,left*, … (delegating tofast-zip.core/right, …)
-
-
new token type
:forms -
new functions in
rewrite-clj.parser:-
parse-all -
parse-string-all -
parse-file-all
-
-
zipper utility functions in
rewrite-clj.zip.utils(able to handle multi-line strings):-
prefix -
suffix
-