

This extension provides a syntax for string interpolation. Here is an example of
its features:

#+begin_src ocaml
let script_remotely (user : string) (host : string) (port : int) (script : string) =
  [%string "ssh %{user}@%{host} -p %{port#Int} %{Sys.quote script}"]
#+end_src

The above expression is equivalent to:

#+begin_src ocaml
let script_remotely (user : string) (host : string) (port : int) (script : string) =
  String.concat ""
    [ "ssh "
    ; user
    ; "@"
    ; host
    ; " -p "
    ; Int.to_string port
    ; " "
    ; Sys.quote script
    ]
#+end_src

Compared to =Printf.sprintf=:

#+begin_src ocaml
let script_remotely (user : string) (host : string) (port : int) (script : string) =
  sprintf "ssh %s@%s -p %d %s" user host port (Sys.quote script)
#+end_src

having the values inline instead of after the format string can make it easier
to understand the resulting string, and avoids the potential mistake of passing
arguments in the wrong order. This is truer the more format arguments there are.
On the other hand, some things are much easier with printf: pad numbers with
zeroes, pad strings on the right, display floats in a specific formats, etc.

Compared to manually writing something like =String.concat= version above,
ppx_string is shorter and can oftentimes be less error-prone (it's really easy
to forget whitespace after =ssh= or around =-p= in the explicit =String.concat=
version).

To emit the literal sequence =%{=, you can escape it as follows:

#+begin_src ocaml
[%string {|%{"%{"}|}]
#+end_src

To pad strings with spaces on the left, add an integer expression after a colon:

#+begin_src ocaml
[%string "%{col1#Int:term_width / 2}%{col2#:term_width/4}%{col3#:8}%{col4}"]
#+end_src

is equivalent to:

#+begin_src ocaml
  let pad str len =
    let pad_len = max 0 (len - String.length str) in
    let padding = String.make pad_len ' ' in
    padding ^ str
  in
  String.concat ""
    [ pad (Int.to_string col1) (term_width / 2)
    ; pad col2 (term_width / 4)
    ; pad col3 8
    ; col4
    ]
#+end_src
(note that the pad length can be dynamic, as with the format string "%*s")
