<?xml version="1.0" encoding="utf-8"?>
<rss version="2.0">
<channel>
<title>Clojure Q&amp;A - Recent activity in tools.reader</title>
<link>https://ask.clojure.org/index.php/activity/contrib-libs/tools-reader</link>
<description></description>
<item>
<title>Answer selected: tools.reader project file version is outdated</title>
<link>https://ask.clojure.org/index.php/15209/tools-reader-project-file-version-is-outdated?show=15210#a15210</link>
<description>&lt;p&gt;Contrib libraries are built with Maven, not Leiningen. Any &lt;code&gt;project.clj&lt;/code&gt; files were added by the individual maintainers, purely for their own convenience, and should not be relied on.&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/15209/tools-reader-project-file-version-is-outdated?show=15210#a15210</guid>
<pubDate>Mon, 24 Aug 2026 14:38:56 +0000</pubDate>
</item>
<item>
<title>Closed: clojure.tools.reader.edn/read can cause incorrect column number for token at end of input</title>
<link>https://ask.clojure.org/index.php/14437/clojure-tools-reader-cause-incorrect-column-number-token-input?show=14437#q14437</link>
<description>&lt;p&gt;&lt;strong&gt;Context&lt;/strong&gt;&lt;br&gt;
A user reported that &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clj-commons/rewrite-clj/issues/367&quot;&gt;rewrite-clj column number metadata can be incorrect for a token at the end of input&lt;/a&gt;. &lt;/p&gt;
&lt;p&gt;Rewrite-clj uses clojure.tools/reader to read clojure source.&lt;br&gt;
It uses &lt;code&gt;clojure.tools.reader.reader-types/get-column-number&lt;/code&gt; to discover the current column offset.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Affected&lt;/strong&gt;&lt;br&gt;
clojure.tools/reader v1.3.4 through v1.5.0&lt;br&gt;
Clojure only (not ClojureScript)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Env&lt;/strong&gt;&lt;br&gt;
On Linux using Clojure CLI 1.12.0.1517 with JDK 23.0.2 (temurin)&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Symptom&lt;/strong&gt;&lt;br&gt;
When the element at end of input is a token, after it is read, the column number is one less than it should be.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Setup&lt;/strong&gt;&lt;br&gt;
Let's setup a playground in &lt;code&gt;foo.clj&lt;/code&gt;&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;(ns foo
  (:require [clojure.pprint :refer [pprint]]
            [clojure.tools.reader.edn :as edn]
            [clojure.tools.reader.reader-types :as rt]))

(defn reader [s]
  (-&amp;gt; s
      rt/string-push-back-reader
      rt/indexing-push-back-reader))

(defn dump-with-cols [s]
  (println &quot;input string:&quot; s)
  (println &quot;colnums:     &quot; (apply str (take (inc (count s)) (cycle [1 2 3 4 5 6 7 8 9 0])))))

(defn read-by-obj [s]
  (with-open [r (reader s)]
    (loop [acc [{:at :bof :col-number (rt/get-column-number r)}]
           obj (edn/read r false ::eof {})]
      (if (not= ::eof obj)
        (recur (conj acc {:after obj :col-number (rt/get-column-number r)})
               (edn/read r false ::eof {}))
        (conj acc {:at :eof :col-number (rt/get-column-number r)})))))

(let [s (first *command-line-args*)]
  (dump-with-cols s)
  (println &quot;parse result:&quot;)
  (pprint (read-by-obj s)))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Reproduction&lt;/strong&gt;&lt;br&gt;
Using clojure.tools/reader v1.5.0:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.5.0&quot;}}}' \
        -M foo.clj ':bip :bop'
input string: :bip :bop
colnums:      1234567890
parse result:
[{:at :bof, :col-number 1}
 {:after :bip, :col-number 5}
 {:after :bop, :col-number 9}
 {:at :eof, :col-number 9}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;Notice after &lt;code&gt;:bip&lt;/code&gt; we see the correct &lt;code&gt;:col-number 5&lt;/code&gt;, but after &lt;code&gt;:bop&lt;/code&gt; we see the incorrect &lt;code&gt;:col-number 9&lt;/code&gt;; it should be &lt;code&gt;:col-number 10&lt;/code&gt;.&lt;/p&gt;
&lt;p&gt;An incorrect column number occurs for any unwrapped last token, a number:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.5.0&quot;}}}' \
        -M foo.clj 123
input string: 123
colnums:      1234
parse result:
[{:at :bof, :col-number 1}
 {:after 123, :col-number 3}
 {:at :eof, :col-number 3}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;a symbol:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.5.0&quot;}}}' \
        -M foo.clj x
input string: x
colnums:      12
parse result:
[{:at :bof, :col-number 1}
 {:after x, :col-number 1}
 {:at :eof, :col-number 1}]

&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;But we get a correct result for syntax wrapped elements:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.5.0&quot;}}}' \
        -M foo.clj '(x)'
input string: (x)
colnums:      1234
parse result:
[{:at :bof, :col-number 1}
 {:after (x), :col-number 4}
 {:at :eof, :col-number 4}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;&lt;strong&gt;Diagnosis&lt;/strong&gt;&lt;br&gt;
If I dial clojure.tools/reader back to v1.3.3, I don't see the issue:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.3.3&quot;}}}' \
        -M foo.clj ':bip :bop'
input string: :bip :bop
colnums:      1234567890
parse result:
[{:at :bof, :col-number 1}
 {:after :bip, :col-number 5}
 {:after :bop, :col-number 10}
 {:at :eof, :col-number 10}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;And then bump one version to v1.3.4, I see the issue:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;$ clojure -Sdeps '{:deps {org.clojure/tools.reader {:mvn/version &quot;1.3.4&quot;}}}' \
        -M foo.clj ':bip :bop'
input string: :bip :bop
colnums:      1234567890
parse result:
[{:at :bof, :col-number 1}
 {:after :bip, :col-number 5}
 {:after :bop, :col-number 9}
 {:at :eof, :col-number 9}]
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;There was &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/tools.reader/commit/c8981dd6ac7a560db85321b03278d03caf2aed39&quot;&gt;only one significant change between v1.3.3 and v1.3.4&lt;/a&gt;.&lt;/p&gt;
&lt;p&gt;Unreading the character at eof is causing the off-by-one issue.&lt;/p&gt;
&lt;p&gt;If I change the &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/clojure/tools.reader/blob/30d9f1d04417adc222ab57178dfd56d5d7a01d58/src/main/clojure/clojure/tools/reader/edn.clj#L54-L63&quot;&gt;existing&lt;/a&gt;:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  (loop [sb (StringBuilder.)
         ch initch]
    (if (or (whitespace? ch)
            (macro-terminating? ch)
            (nil? ch))
      (do (unread rdr ch)
          (str sb))
      (if (not-constituent? ch)
        (err/throw-bad-char rdr kind ch)
        (recur (doto sb (.append ch)) (read-char rdr))))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;To:&lt;/p&gt;
&lt;pre&gt;&lt;code&gt;  (loop [sb (StringBuilder.)
         ch initch]
    (cond
      (or (whitespace? ch)
          (macro-terminating? ch))
      (do (unread rdr ch)
          (str sb))

      (nil? ch)
      (str sb)

      (not-constituent? ch)
      (err/throw-bad-char rdr kind ch)

      :else
      (recur (doto sb (.append ch)) (read-char rdr)))))))
&lt;/code&gt;&lt;/pre&gt;
&lt;p&gt;The problem is resolved for me.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Next Steps&lt;/strong&gt;&lt;br&gt;
Happy to contribute a patch if the above makes sense to you and you think it is worthwhile to fix.&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14437/clojure-tools-reader-cause-incorrect-column-number-token-input?show=14437#q14437</guid>
<pubDate>Tue, 18 Mar 2025 14:31:27 +0000</pubDate>
</item>
<item>
<title>Commented: tools.reader parse-symbol is too sloppy when reading new n-dimensional class array</title>
<link>https://ask.clojure.org/index.php/14065/tools-reader-parse-symbol-sloppy-reading-dimensional-class?show=14081#c14081</link>
<description>Thanks. The perf issue was just a bonus. The main problem was:&lt;br /&gt;
&lt;br /&gt;
Tools.reader accepts this symbol: MyClazz:/3 while it does not accept the symbol MyClass:. This seems inconsistent. That's the main subject of this &amp;quot;ask&amp;quot;.</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/14065/tools-reader-parse-symbol-sloppy-reading-dimensional-class?show=14081#c14081</guid>
<pubDate>Thu, 22 Aug 2024 15:38:53 +0000</pubDate>
</item>
<item>
<title>Commented: Support Clojure 1.12-alpha12 Array class notation</title>
<link>https://ask.clojure.org/index.php/13906/support-clojure-1-12-alpha12-array-class-notation?show=13920#c13920</link>
<description>i wrote a patch because i'm eager and had some free time, but that makes sense.</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13906/support-clojure-1-12-alpha12-array-class-notation?show=13920#c13920</guid>
<pubDate>Sat, 25 May 2024 12:24:22 +0000</pubDate>
</item>
<item>
<title>Answer selected: sending cljs file to repl causes reader exception</title>
<link>https://ask.clojure.org/index.php/13434/sending-cljs-file-to-repl-causes-reader-exception?show=13445#a13445</link>
<description>&lt;p&gt;The issue should be fixed as of shadow-cljs 2.26.0, or rather tools.reader 1.3.7 which was the cause of the problem and is now the declared dependency.&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/13434/sending-cljs-file-to-repl-causes-reader-exception?show=13445#a13445</guid>
<pubDate>Thu, 09 Nov 2023 18:38:21 +0000</pubDate>
</item>
<item>
<title>Commented: Clojure Tools Reader intent regarding newline normalization?</title>
<link>https://ask.clojure.org/index.php/12216/clojure-tools-reader-intent-regarding-newline-normalization?show=12220#c12220</link>
<description>Oh right, yes, good point! Thanks for your patience on this.&lt;br /&gt;
&lt;br /&gt;
Rewrite-clj digs deeper into tools.reader than most users might.&lt;br /&gt;
&lt;br /&gt;
It makes use of clojure.tools.reader.reader-types namespace using fns like read-char, unread and peekchar. &amp;nbsp;It takes this lower level approach to return things the higher level reader fns do not return, like whitespace, comments and #_ :skipped-stuff.&lt;br /&gt;
&lt;br /&gt;
So when rewrite-clj gets that whitespace, the newlines are always \n (even if they were originally \r\n).</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/12216/clojure-tools-reader-intent-regarding-newline-normalization?show=12220#c12220</guid>
<pubDate>Mon, 19 Sep 2022 22:53:00 +0000</pubDate>
</item>
<item>
<title>Commented: No metadata on clojure 1.9 map literals</title>
<link>https://ask.clojure.org/index.php/10724/no-metadata-on-clojure-1-9-map-literals?show=10779#c10779</link>
<description>And Nicola fixed it right away and released a v1.3.6 with the fix. Thanks to both of you!</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10724/no-metadata-on-clojure-1-9-map-literals?show=10779#c10779</guid>
<pubDate>Tue, 13 Jul 2021 21:25:14 +0000</pubDate>
</item>
<item>
<title>Answer edited: Looking for a safe way to read EDN with file position metadata</title>
<link>https://ask.clojure.org/index.php/10722/looking-for-safe-way-to-read-edn-with-file-position-metadata?show=10723#a10723</link>
<description>&lt;p&gt;I ended up switching to &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/borkdude/edamame&quot;&gt;https://github.com/borkdude/edamame&lt;/a&gt;&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/10722/looking-for-safe-way-to-read-edn-with-file-position-metadata?show=10723#a10723</guid>
<pubDate>Wed, 23 Jun 2021 08:41:31 +0000</pubDate>
</item>
<item>
<title>Answer selected: How to read namespaced keywords with clojure.tools.reader/read?</title>
<link>https://ask.clojure.org/index.php/8856/how-read-namespaced-keywords-with-clojure-tools-reader-read?show=8857#a8857</link>
<description>&lt;p&gt;If you know how to resolve the autoresolved keyword aliases, you can set the &lt;code&gt;*alias-map*&lt;/code&gt; dynamic binding and plug something in there: &lt;a rel=&quot;nofollow&quot; href=&quot;http://clojure.github.io/tools.reader/#clojure.tools.reader/*alias-map*&quot;&gt;http://clojure.github.io/tools.reader/#clojure.tools.reader/*alias-map*&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;It's described as a map, but it's invoked as a function, so I think a function would work too. &lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8856/how-read-namespaced-keywords-with-clojure-tools-reader-read?show=8857#a8857</guid>
<pubDate>Mon, 18 Nov 2019 18:07:37 +0000</pubDate>
</item>
<item>
<title>Answered: Possibility to ignore read-eval?</title>
<link>https://ask.clojure.org/index.php/8702/possibility-to-ignore-read-eval?show=8703#a8703</link>
<description>&lt;p&gt;Doesn't sound like a good idea to me. There are some other Clojure parsers out there that might better suit your needs like &lt;a rel=&quot;nofollow&quot; href=&quot;https://github.com/borkdude/edamame&quot;&gt;https://github.com/borkdude/edamame&lt;/a&gt;.&lt;/p&gt;
</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8702/possibility-to-ignore-read-eval?show=8703#a8703</guid>
<pubDate>Wed, 09 Oct 2019 13:40:33 +0000</pubDate>
</item>
<item>
<title>Answered: The error feedback from the read-string function would be improved if it used an indexing reader.</title>
<link>https://ask.clojure.org/index.php/8105/error-feedback-string-function-would-improved-indexing-reader?show=8108#a8108</link>
<description>Reference: &lt;a href=&quot;https://clojure.atlassian.net/browse/TRDR-45&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://clojure.atlassian.net/browse/TRDR-45&lt;/a&gt; (reported by alex+import)</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8105/error-feedback-string-function-would-improved-indexing-reader?show=8108#a8108</guid>
<pubDate>Wed, 26 Jun 2019 12:00:00 +0000</pubDate>
</item>
<item>
<title>Answered: Partial parses and complete source info (i.e. info on atoms without metadata)</title>
<link>https://ask.clojure.org/index.php/8106/partial-parses-complete-source-info-atoms-without-metadata?show=8109#a8109</link>
<description>Reference: &lt;a href=&quot;https://clojure.atlassian.net/browse/TRDR-49&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://clojure.atlassian.net/browse/TRDR-49&lt;/a&gt; (reported by bhauman)</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8106/partial-parses-complete-source-info-atoms-without-metadata?show=8109#a8109</guid>
<pubDate>Wed, 26 Jun 2019 12:00:00 +0000</pubDate>
</item>
<item>
<title>Answered: Simple benchmarking bash script to test before &amp; after applying a batch</title>
<link>https://ask.clojure.org/index.php/8104/simple-benchmarking-bash-script-before-after-applying-batch?show=8107#a8107</link>
<description>Reference: &lt;a href=&quot;https://clojure.atlassian.net/browse/TRDR-29&quot; rel=&quot;nofollow&quot; target=&quot;_blank&quot;&gt;https://clojure.atlassian.net/browse/TRDR-29&lt;/a&gt; (reported by dnolen)</description>
<category>tools.reader</category>
<guid isPermaLink="true">https://ask.clojure.org/index.php/8104/simple-benchmarking-bash-script-before-after-applying-batch?show=8107#a8107</guid>
<pubDate>Wed, 26 Jun 2019 12:00:00 +0000</pubDate>
</item>
</channel>
</rss>