Welcome! Please see the About page for a little more info on how this works.

0 votes
in Printing by
edited by

I'd like to pprint a data structure, where the whole thing is printed indented. (As if, for example, I was already some levels deep).

(pprint x)
{:foo ...
 :bar ...}

(pprint-with-indentation x)
    {:foo ...
     :bar ...}

I tried calling pprint-indent before pprint, but that didn't work (or I was using it wrong!)

Stel commented with a solution of adding the indentation after running pprint. This would certainly work; I was looking more specifically to ask if there was a way to get pprint to do it (so that the output would continue to conform to *print-right-margin* etc. without adjusting the margins myself). Of course, if there isn't a way to do that, Stel's solution is a good workaround.

Any ideas of what I could try?

Thanks!

Andrew

1 Answer

+1 vote
by
edited by

Hi there Andrew,

I saw this on Twitter and it got my gears turning. You could use with-out-str and add the indentation at the beginning and after all the newline chars. There's definitely a more efficient way to do it but this gets the job done:

Note: Edited with Andrew's suggestion to change *print-right-margin* value

(require '[clojure.pprint :as pprint])

(defn gen-pprint-with-indentation [indent-num]
  (fn pprint-with-indentation [x]
    (let [indent-str (->> \space repeat (take indent-num) (apply str))
          new-margin (- pprint/*print-right-margin* indent-num)]
      (binding [pprint/*print-right-margin* new-margin]
        (->> x
             pprint/pprint
             with-out-str
             (map #(if (= \newline %) (str \newline indent-str) %))
             (apply str indent-str)
             println)))))

(def data {:hi :there
           :wow {:much :pprint
                 :ok [:cooljflksdjfdslkfjkldsjskdlfjsdlkfjksldjfslkj]
                 :seriously {:hi "hiiiiiiiiiiiiii"}}})

(def pprint-5 (gen-pprint-with-indentation 5))

(pprint-5 data)
by
Thank you Stel!

This is a good solution if there isn't a way to tell pprint to start with a specific indentation.

I note that since here the indentation is applied externally to pprint, using this approach we'd probably also want to adjust e.g. `*print-right-margin*` etc. if we want the pretty-printed output to stay within its usual margins.
by
Oh nice catch! I didn't think about the margin. I'll try to update my answer with the *print-right-margin* value in mind.
by
Tom created a repository a long time ago that used a custom dispatch function to use a 2-space indent instead of one. There may be something useful in there, but I haven't had a chance to look deeply. https://github.com/tomfaulhaber/pprint-indent
by
Thank you Fogus!
...