Skip to content

Instantly share code, notes, and snippets.

@sogaiu
Last active September 11, 2020 11:05
Show Gist options
  • Save sogaiu/2be50c906e52a686699c154d4423c91d to your computer and use it in GitHub Desktop.
Save sogaiu/2be50c906e52a686699c154d4423c91d to your computer and use it in GitHub Desktop.
expanding defdirectives from clojure.pprint (cl_format.clj)
{
:hooks {:analyze-call {clojure.pprint/defdirectives hooks.clojure.pprint.defdirectives/defdirectives}}
}
(ns hooks.clojure.pprint.defdirectives
"The defdirectives macro from clojure/pprint/cl_format.clj"
(:require [clj-kondo.hooks-api :as api]))
;; from clojure/pprint/cl_format.clj
;; (defn- process-directive-table-element
;; [[char params flags bracket-info & generator-fn]]
;; [char,
;; {:directive char,
;; :params `(array-map ~@params),
;; :flags flags,
;; :bracket-info bracket-info,
;; :generator-fn (concat '(fn [params offset]) generator-fn)}])
;; (defmacro ^{:private true}
;; defdirectives
;; [& directives]
;; `(def ^{:private true}
;; directive-table
;; (hash-map ~@(mapcat process-directive-table-element directives))))
(defn defdirectives
"Private macro in clojure/pprint/cl_format.clj.
Example call:
(defdirectives
(\\A
[:mincol [0 Integer]
:colinc [1 Integer]
:minpad [0 Integer]
:padchar [\\space Character]]
#{:at :colon :both}
{}
#(format-ascii print-str %1 %2 %3))
,,, ;; and so on
)
This has the form:
(defdirectives <list-0> ... <list-n>)
where <list-i> is a group of 1 + 4 things.
directive-table is then defined as a map:
;; XXX: skipping the private metadata part
(def directive-table
{\\A {:directive \\A,
:params {:mincol [0 java.lang.Integer],
:colinc [1 java.lang.Integer],
:minpad [0 java.lang.Integer],
:padchar [\\space java.lang.Character]},
:flags #{:colon :at :both},
:bracket-info {},
:generator-fn #(format-ascii print-str %1 %2 %3)}
,,, ;; and so on
})
Roughly, each group of 1 + 4 things from the input <list-i> ends up
as a key-value pair.
Adapting hints from borkdude and lread, target is:
(def directive-table
;; don't bother with making a map
[[\\A [:directive \\A,
;; no map here either
:params [:mincol [0 java.lang.Integer],
:colinc [1 java.lang.Integer],
:minpad [0 java.lang.Integer],
:padchar [\\space java.lang.Character]],
:flags #{:colon :at :both},
:bracket-info {},
:generator-fn #(format-ascii print-str %1 %2 %3)]
,,, ;; and so on
])
"
[{:keys [:node]}]
(let [[_ & list-nodes] (:children node)
v-nodes (map
(fn [list-node]
(let [[d-node p-node f-node b-node g-node]
(:children list-node)]
(api/vector-node
[d-node p-node f-node b-node
(api/list-node [(api/token-node 'fn)
(api/vector-node [(api/token-node 'params)
(api/token-node 'offset)])
g-node])])))
list-nodes)
new-node (api/list-node
[(api/token-node 'def)
(api/token-node 'directive-table)
(api/vector-node v-nodes)])]
;; XXX: uncomment following and run clj-kondo on cl_format.clj to debug
;;(prn (api/sexpr new-node))
{:node new-node}))
(comment
(defn- process-directive-table-element
[[char params flags bracket-info & generator-fn]]
[char,
{:directive char,
:params `(array-map ~@params),
:flags flags,
:bracket-info bracket-info,
:generator-fn (concat '(fn [params offset]) generator-fn)}])
(defmacro ^{:private true}
defdirectives
[& directives]
`(def ^{:private true}
directive-table
(hash-map ~@(mapcat process-directive-table-element directives))))
)
(require 'clojure.pprint)
(in-ns 'clojure.pprint)
(defdirectives
(\A
[:mincol [0 Integer]
:colinc [1 Integer]
:minpad [0 Integer]
:padchar [\space Character]]
#{:at :colon :both}
{}
#(format-ascii print-str %1 %2 %3))
(\S
[:mincol [0 Integer]
:colinc [1 Integer]
:minpad [0 Integer]
:padchar [\space Character]]
#{:at :colon :both}
{}
#(format-ascii pr-str %1 %2 %3))
,,,
)
directive-table
#_ {\A {:directive \A,
:params {:mincol [0 java.lang.Integer],
:colinc [1 java.lang.Integer],
:minpad [0 java.lang.Integer],
:padchar [\space java.lang.Character]},
:flags #{:colon :at :both},
:bracket-info {},
:generator-fn #(format-ascii print-str %1 %2 %3)}
\S {:directive \S,
:params {:mincol [0 java.lang.Integer],
:colinc [1 java.lang.Integer],
:minpad [0 java.lang.Integer],
:padchar [\space java.lang.Character]},
:flags #{:colon :at :both},
:bracket-info {},
:generator-fn #(format-ascii print-str %1 %2 %3)}
,,,
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment