readmoi.core

Functions for generating ReadMoi webpages.

File resources/readmoi_options.edn contains a map with the following key-vals.

Required keys:

  • :sections, and within each section:
    • :section-name
    • :section-href
    • :section-skip-load?

Optional keys:

  • :clojars-badge?
  • :copyright-holder
  • :fn-map-additions
  • :license-hiccup
  • :project-description
  • :project-name-formatted
  • :preferred-project-metadata
  • :readme-UUID
  • :readme-html-directory
  • :readme-html-filename
  • :readme-markdown-directory
  • :readme-markdown-filename
  • :sections-directory
  • :separator
  • :wrap-at
  • :def-patterns

Default values are sourced from the defaults file.

Dynamic vars that govern output formatting:

Dynamic vars that may be referred for creating content (e.g., Setup section):

See project’s documentation for details.

*def-patterns*

dynamic

A set of strings that governs when print-form-then-eval suppresses printing the evaluated value. Defaults to #{"def" "defn" "defmacro"}.

*fn-map-additions*

dynamic

Additional directives to pass to zprint governing formatting specific function invocations. Default {}.

*project-group*

dynamic

Project group as observed in Leiningen project.clj. Defaults to "" (i.e., empty string). Intended to be referenced within hiccup/html section files.

*project-name*

dynamic

Project name as observed in Leiningen project.clj. Defaults to "" (i.e., empty string). Intended to be referenced within hiccup/html section files.

*project-version*

dynamic

Project version as observed in Leiningen project.clj. Defaults to nil. Intended to be referenced within hiccup/html section files.

*separator*

dynamic

Characters that separate the string representation of the form to be evaluated and the string representation of the result. Default =>.

*wrap-at*

dynamic

Base-case column wrap, override-able by supplying extra args to the function that would otherwise consult this value, e.g., print-form-then-eval. Default 80.

-main

(-main & options-filename)

Generate a project ReadMe. Sources options from file options-filename if supplied, otherwise resources/readmoi_options.edn.

Examples:

;; generate ReadMe using options from 'resources/readmoi_options.edn'
(-main)

;; generate ReadMe using options from 'other_directory/custom_readme_opt.edn'
(-main "other_directory/custom_readme_opt.edn")

Running from the command line, there’s a quirk to avoid. The lein run pattern seems to refer only the -main function, but not any of the other useful readmoi.core vars, such as print-form-then-eval, *project-version*, etc.

There are two options for running from the command line:

  1. If the ReadMe contains a small number of them, always write the full, namespace-qualified name, e.g. readmoi.core/print-form-then-eval, readmoi.core/*project-version*, etc. Then, invoke from the command line.

    Default options file ‘resources/readmoi_options.edn’.

    $ lein run -m readmoi.core
    

    Explicit options file ‘other_directory/custom_readme_opt.edn’.

    $ lein run -m readmoi.core other_directory/custom_readme_opt.edn
    
  2. If the ReadMe contains a multitude of readmoi.core references, then assemble a generator script similar to this:

    (ns readmoi-generator
      (:require [*project-version*
                 -main
                 print-form-then-eval]))
    
    (-main)
    

    Invoking -main from inside the generator script’s namespace in a REPL-attached editor permits writing simple names, i.e., print-form-then-eval and *project-version*, without their namespace qualifiers.

    Or, from the command line, lein run can now refer to the needed vars from readmoi.core because they’re require-d by the generator script.

    Default options file ‘resources/readmoi_options.edn’.

    $ lein run -m readmoi-generator
    

    Explicit options file ‘other_directory/custom_readme_opt.edn’.

    $ lein run -m readmoi-generator other_directory/custom_readme_opt.edn
    

html-tidy-defaults

A vector of strings to be supplied to tidy-html as if on the command line. The most notable defaults are:

  • -i indent
  • --quiet limits output report
  • --wrap wrap lines at column 160
  • --write-back over-write original file

long-date

(long-date)

Long-form date+time, with time zone removed.

Example:

(long-date) ;; => "2024-11-16 07:26:53"

prettyfy

(prettyfy s & width)

Apply zprint formatting to string s. Optional integer width over-rides dynamic var *wrap-at*.

Provide zprint alternative function classifications by re-binding *fn-map-additions*.

Examples:

(prettyfy (str (eval (read-string "(repeat 3 (repeat 3 [77 88 99]))"))))
;; => "(([77 88 99] [77 88 99] [77 88 99])\n  ([77 88 99] [77 88 99] [77 88 99])\n  ([77 88 99] [77 88 99] [77 88 99]))"

…which would render to…

(([77 88 99] [77 88 99] [77 88 99])
 ([77 88 99] [77 88 99] [77 88 99])
 ([77 88 99] [77 88 99] [77 88 99]))

print-form-then-eval

(print-form-then-eval str-form)(print-form-then-eval str-form width-fn width-output)

Returns a hiccup [:code] block wrapping a Clojure stringified form str-form, separator sep (default ' => '), and evaluated value.

def, defn, defmacro, and require expressions are only evaled; their output is not printed. These exclusions may be adjusted by associating a new (possibly empty) set of strings to option :def-patterns, or by binding *def-patterns*.

The two optional width args supersede *wrap-at*.

  • width-fn governs the max-width of the rendered str-form. Default *wrap-at*.
  • width-output governs the max-width of the rendered evaluation of str-form. Default (/ *wrap-at* 2).

Re-bind *wrap-at* to change base-case column-wrap width. The two optional width args, width-fn and width-output, supersede this value.

Re-bind *separator* to change the evaluation arrow.

Re-bind *fn-map-additions* to include additional zprint :fn-map directives.

See also prettyfy.

Note: Evaluated output can not contain an anonymous function of either (fn [x] ...) nor #(...) because zprint requires an internal reference to attempt a backtrack. Since the rendering of an anonymous function changes from one invocation to the next, there is no stable reference.

  1. Basic example:

    (print-form-then-eval "(+ 1 2)")
    ;; => [:code "(+ 1 2) ;; => 3"]
    

    After hiccup processing, renders as…

    (+ 1 2) ;; => 3
    
  2. Another example:

    (print-form-then-eval "(map inc (range 1 6))")
    ;; => [:code "(map inc (range 1 6)) ;; => (2 3 4 5 6)"]
    

    Renders as…

    (map inc (range 1 6)) ;; => (2 3 4 5 6)
    
  3. Example with supplied widths:

    (print-form-then-eval "(map inc (range 1 6))" 10 5)
    ;; => [:code "(map inc\n  (range\n    1\n    6))\n;; => (2\n;;     3\n;;     4\n;;     5\n;;     6)"]
    

    Renders as…

    (map inc
    (range
      1
      6))
    ;; => (2
    ;;     3
    ;;     4
    ;;     5
    ;;     6)
    
  4. Example with alternative arrow:

    (binding [*separator* " --->> "]
      (print-form-then-eval "(inc 1)"))
    ;; => [:code "(inc 1) ;; --->> 2"]
    

    Renders as…

    (inc 1) ;; --->> 2
    
  5. Example with alternative ‘def’ pattern:

    ;; note: `defn-` is not included in the default exludes
    (binding [*def-patterns* #{"defn-"}]
      (print-form-then-eval "(defn- foo [x] x)"))
    ;; => [:code "(defn- foo [x] x)"]
    

    Renders as…

    (defn- foo [x] x)
    

random-paragraph

(random-paragraph)

Generate a random alpha-numeric paragraph.

For similar example, see random-sentence.

random-sentence

(random-sentence)

Generates a random alpha-numeric sentence.

Example:

(random-sentence) ;; => "2g  0j45do 2xq n1nwrm 2a41nk g0x47ov v4bbix jo3687i2oh ofrg1o bi 2fc68 15pn1 o82hp3hu49l5d6xhx hk1bgdo2xex2c133bo."

readmoi-defaults

A hash-map residing in readmoi_defaults.clj that supplies the default values for the following options keys:

  • :clojars-badge
  • :license-hiccup
  • :sections-directory
  • :readme-html-directory
  • :readme-html-filename
  • :readme-markdown-directory
  • :readme-markdown-filename
  • :tidy-html?

Override default values by associating new values into the ReadMoi options hash-map. See also the readmoi.core namespace docstring.

short-date

(short-date)

Short-form date, named month.

Example:

(short-date) ;; => "2024 November 16"

test-run

(test-run)

tidy-html-body

(tidy-html-body f)(tidy-html-body f options)

Given html body (or substantially html-like markdown), contained in file pathname string f, use tidy-html to wrap and indent the html. Tidy-ing settings may be supplied by options vector, which completely replaces html-tidy-defaults.

Useful for tidy-ing only an html body for supplying to GitHub’s markdown processor.

Requires local installation of html-tidy.

See also tidy-html-document for a similar utility that operates on a full html document.

tidy-html-document

(tidy-html-document f)(tidy-html-document f options)

For html document (or substantially html-like markdown), contained in file pathname string f, use tidy-html to wrap and indent the html. Tidy-ing settings may be supplied by options vector, which completely replaces html-tidy-defaults.

Requires local installation of html-tidy.

Note: This utility delegates the tidy-ing task to tidy-html, which insists on adding a missing html head, title, etc. To tidy a fragment, i.e., an html body, use tidy-html-body.

Note: When tidy-ing, in-line [:code ...] blocks et. al., may be broken over lines at an undesirable space. Use a Unicode non-breaking space, U+00A0, to maintain a coherent block. An html non-breaking space entity,   renders literally, and thus not suitable for this purpose.