Skip to content

Commit 187497a

Browse files
committed
Rewrite-clj now understands #! comments
Fixes #145
1 parent 59668f5 commit 187497a

File tree

8 files changed

+51
-22
lines changed

8 files changed

+51
-22
lines changed

CHANGELOG.adoc

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ For a list of breaking changes see link:#v1-breaking[breaking changes].
1616

1717
=== Unreleased
1818

19+
* rewrite-clj now understands the `#!` comment, a construct often used in scripts https://github.com/clj-commons/rewrite-clj/issues/145[#145]
20+
1921
=== v1.0.594-alpha
2022

2123
* rewrite-clj now explicitly depends on the minimum version of Clojure required, v1.9.0, rather than v1.10.3 https://github.com/clj-commons/rewrite-clj/issues/142[#142]

src/rewrite_clj/node.cljc

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -210,18 +210,25 @@
210210
(defn comment-node
211211
"Create node representing a comment with text `s`.
212212
213-
`s` should:
214-
- not specify the first leading semicolon
215-
- usually include the trailing newline character, otherwise subsequent nodes will be on the comment line
213+
You may optionally specify a `prefix` of `\";\"` or `\"#!\"`, defaults is `\";\"`.
214+
215+
Argument `s`:
216+
- must not include the `prefix`
217+
- usually includes the trailing newline character, otherwise subsequent nodes will be on the comment line
216218
217219
```Clojure
218220
(require '[rewrite-clj.node :as n])
219221
220222
(-> (n/comment-node \"; my comment\\n\")
221223
n/string)
222224
;; => \";; my comment\\n\"
225+
226+
(-> (n/comment-node \"#!\" \"/usr/bin/env bb\\n\")
227+
n/string)
228+
;; => \"#!/usr/bin/env bb\\n\"
223229
```"
224-
[s] (rewrite-clj.node.comment/comment-node s))
230+
([s] (rewrite-clj.node.comment/comment-node s))
231+
([prefix s] (rewrite-clj.node.comment/comment-node prefix s)))
225232

226233
;; DO NOT EDIT FILE, automatically imported from: rewrite-clj.node.comment
227234
(defn comment?

src/rewrite_clj/node/comment.cljc

Lines changed: 18 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,17 +5,17 @@
55

66
;; ## Node
77

8-
(defrecord CommentNode [s]
8+
(defrecord CommentNode [prefix s]
99
node/Node
1010
(tag [_node] :comment)
1111
(node-type [_node] :comment)
1212
(printable-only? [_node] true)
1313
(sexpr* [_node _opts]
1414
(throw (ex-info "unsupported operation" {})))
1515
(length [_node]
16-
(+ 1 (count s)))
16+
(+ (count prefix) (count s)))
1717
(string [_node]
18-
(str ";" s))
18+
(str prefix s))
1919

2020
Object
2121
(toString [node]
@@ -28,20 +28,29 @@
2828
(defn comment-node
2929
"Create node representing a comment with text `s`.
3030
31-
`s` should:
32-
- not specify the first leading semicolon
33-
- usually include the trailing newline character, otherwise subsequent nodes will be on the comment line
31+
You may optionally specify a `prefix` of `\";\"` or `\"#!\"`, defaults is `\";\"`.
32+
33+
Argument `s`:
34+
- must not include the `prefix`
35+
- usually includes the trailing newline character, otherwise subsequent nodes will be on the comment line
3436
3537
```Clojure
3638
(require '[rewrite-clj.node :as n])
3739
3840
(-> (n/comment-node \"; my comment\\n\")
3941
n/string)
4042
;; => \";; my comment\\n\"
43+
44+
(-> (n/comment-node \"#!\" \"/usr/bin/env bb\\n\")
45+
n/string)
46+
;; => \"#!/usr/bin/env bb\\n\"
4147
```"
42-
[s]
43-
{:pre [(re-matches #"[^\r\n]*[\r\n]?" s)]}
44-
(->CommentNode s))
48+
([s]
49+
(comment-node ";" s))
50+
([prefix s]
51+
{:pre [(and (re-matches #"[^\r\n]*[\r\n]?" s)
52+
(or (= prefix ";") (= prefix "#!")))]}
53+
(->CommentNode prefix s)))
4554

4655
(defn comment?
4756
"Returns true if `node` is a comment."

src/rewrite_clj/parser/core.cljc

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
(ns ^:no-doc rewrite-clj.parser.core
22
(:require ;; using internal node nses rather than public rewrite-clj.node
3-
;; allows us to use rewrite-clj to generate code for import-vars target nses
3+
;; allows us to use rewrite-clj to generate code for import-vars target nses
44
[rewrite-clj.node.comment :refer [comment-node]]
55
[rewrite-clj.node.fn :refer [fn-node]]
66
[rewrite-clj.node.meta :refer [meta-node raw-meta-node]]
@@ -98,7 +98,7 @@
9898
(defmethod parse-next* :comment
9999
[#?(:cljs ^not-native reader :default reader)]
100100
(reader/ignore reader)
101-
(comment-node (reader/read-include-linebreak reader)))
101+
(comment-node ";" (reader/read-include-linebreak reader)))
102102

103103
;; ### Special Values
104104

@@ -123,12 +123,17 @@
123123
(reader/unread reader \#)
124124
(parse-token reader))
125125

126+
(defn- parse-shebang-comment [reader]
127+
(reader/ignore reader)
128+
(comment-node "#!" (reader/read-include-linebreak reader)))
129+
126130
(defmethod parse-next* :sharp
127131
[#?(:cljs ^not-native reader :default reader)]
128132
(reader/ignore reader)
129133
(case (reader/peek reader)
130134
nil (reader/throw-reader reader "Unexpected EOF.")
131-
\# (read-symbolic-value reader)
135+
\# (read-symbolic-value reader)
136+
\! (parse-shebang-comment reader)
132137
\{ (set-node (parse-delim reader \}))
133138
\( (fn-node (parse-delim reader \)))
134139
\" (regex-node (parse-regex reader))

test/rewrite_clj/node/coercer_test.cljc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@
2020
;; numbers
2121

2222
;; note that we do have an integer-node, but rewrite-clj never parses to it
23-
;; so we never coerce to it either
23+
;; so we never coerce to it either
2424
3 :token :token
2525
3N :token :token
2626
3.14 :token :token
@@ -159,6 +159,7 @@
159159
(is (= ?tag (node/tag n)))
160160
(is (= ?type (protocols/node-type n))))
161161
";; comment" :comment :comment
162+
"#! comment" :comment :comment
162163
"#(+ 1 %)" :fn :fn
163164
":my-kw" :token :keyword
164165
"^:m1 [1 2 3]" :meta :meta

test/rewrite_clj/node/generators.cljc

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,10 @@
88

99
(def comment-node
1010
(gen/fmap
11-
(fn [[text eol]]
12-
(node/comment-node (str text eol)))
11+
(fn [[prefix text eol]]
12+
(node/comment-node prefix (str text eol)))
1313
(gen/tuple
14+
(gen/elements [";" "#!"])
1415
(gen/such-that
1516
#(re-matches #"[^\r\n]*" %)
1617
gen/string-ascii)

test/rewrite_clj/node_test.cljc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
(is (= ?expected-sexpr-able? (n/sexpr-able? n))))
1616
"," :comma :comma false
1717
"; comment" :comment :comment false
18+
"#! comment" :comment :comment false
1819
"@deref" :deref :deref true
1920
"#(fn %1)" :fn :fn true
2021
":my-kw" :token :keyword true

test/rewrite_clj/parser_test.cljc

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -318,7 +318,10 @@
318318
";"
319319
";;"
320320
";\n"
321-
";;\n"))
321+
";;\n"
322+
"#!shebang comment\n"
323+
"#! this is a comment"
324+
"#!\n"))
322325

323326
(deftest t-parsing-auto-resolve-keywords
324327
(are [?s ?sexpr-default ?sexpr-custom]
@@ -345,7 +348,7 @@
345348
"#:abc {:x 1, :y 1}"
346349
{:abc/x 1, :abc/y 1}
347350

348-
"#:abc ,,, \n\n {:x 1 :y 2}"
351+
"#:abc ,,, \n\n {:x 1 :y 2}"
349352
{:abc/x 1, :abc/y 2}
350353

351354
"#:foo{:kw 1, :n/kw 2, :_/bare 3, 0 4}"
@@ -391,7 +394,7 @@
391394
{:?_current-ns_?/a {:?_current-ns_?/b 1}}
392395
{:booya.fooya/a {:booya.fooya/b 1}}))
393396

394-
(deftest parsing-auto-resolve-ns-alias-maps
397+
(deftest parsing-auto-resolve-ns-alias-maps
395398
(are [?s ?sexpr-default ?sexpr-custom]
396399
(let [n (p/parse-string ?s)]
397400
(is (= :namespaced-map (node/tag n)))

0 commit comments

Comments
 (0)