[cwn] Attn: Development Editor, Latest OCaml Weekly News
Alan Schmitt
alan.schmitt at polytechnique.org
Tue Apr 2 06:26:38 PDT 2019
Hello
Here is the latest OCaml Weekly News, for the week of March 26 to
April
02, 2019.
Table of Contents
─────────────────
Cstruct.4.0.0: sexplib goes optional
New library - uritemplate 0.1.0
Check opam's health for the upcoming OCaml release (4.08)
Turn echoing off on standard input to read e.g. passwords
http2/af: An HTTP/2 implementation for OCaml
Release of OCamlFormat 0.9
Other OCaml News
Old CWN
Cstruct.4.0.0: sexplib goes optional
════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/cstruct-4-0-0-sexplib-goes-optional/3580/1>
Anil Madhavapeddy announced
───────────────────────────
A headsup about a forthcoming backwards incompatible change to
the
cstruct 4.0.0 release. We've been reducing the required
dependencies
of the core Mirage libraries to make the 'hello world'
unikernels as
small as possible. As part of that, cstruct (along with its
good
friends ipaddr and uri) have moved sexplib into a separate
optional
module.
From the changes file:
• Sexplib is now an optional library for the base `Cstruct'
module. A
new `Cstruct_sexp' module has been introduced with the
serialiser
functions, contained within the `cstruct-sexp' opam package.
To convert old code, simply use `Cstruct_sexp.t' instead of
`Cstruct.t' in a record type for which you are using
`[@@deriving
sexp]'. This is a type alias to `Cstruct.t' but also has the
right
sexp-conversion functions in scope. There is an example of
this in
the `ppx_test/with-sexp' directory in the source repo.
When you have converted and released your library, add an opam
constraint of `cstruct {>="4.0.0"}' to your own opam packages
to
ensure that they pick up this version of the library.
The opam repository PR with the full changeset is at :
<https://github.com/ocaml/opam-repository/pull/13748>
New library - uritemplate 0.1.0
═══════════════════════════════
Archive:
<https://discuss.ocaml.org/t/new-library-uritemplate-0-1-0/3588/1>
Corin Chaplin announced
───────────────────────
I am happy to announce my first library published to opam:
uritemplate! The library is a OCaml implementation of URI
templates
([RFC6570]).
Currently it only provides basic functionality but is compliant
to
level 4 of the specification. I am looking at adding more
functionality, such as a Template.t type, so templates can be
parsed
and then templated multiple times.
The repository is [here], the README and documentation is a bit
lacking at the moment, but any feedback would be very much
appreciated
:slight_smile:
[RFC6570] <https://tools.ietf.org/html/rfc6570>
[here] <https://github.com/CorinChappy/uritemplate-ocaml>
Check opam's health for the upcoming OCaml release (4.08)
═════════════════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/check-opams-health-for-the-upcoming-ocaml-release-4-08/3586/1>
Kate announced
──────────────
Like [last month], I'm here to announce new features and news
from
[check.ocamllabs.io].
To recall, this website is an interface to find out which opam
packages are broken with a given set of OCaml compilers. This
month's
features are especially useful to look for missing or broken
packages
for the upcoming OCaml 4.08.
What's new:
• A new type of failures has appeared: internal failures (in
white). Those were previously mistakenly categorized as a
normal
build failure but are usually far from it. It includes: solver
failures, unavailable external dependencies, temporary misc
server
failures, …
• Not available packages are now not skipped but have now logs
attached to them. It makes the total check run longer but is
extremely useful to understand why does packages are not
available
(e.g. which dependencies are blocking, …)
Minor features:
• I have adopted a new name for the underlying tool:
[opam-health-check]
• Under advice from @kkazuo, @grayswandyr and @Ronan in the
previous
post, I have adopted a new colour palette less ambiguous to
both
colorblinds and non-colorblinds (at least I hope)
• Slack integration (see more below)
What's next:
• Due to the ever growing number of opam packages and solver
shenanigans, some solver failures can appear, especially on a
server
with a lot of packages building in parallel. For now
opam-health-check uses the [SYMPHONY] solver instead of the
builtin
solver to mitigate that. However some failures still appear
and I'm
looking to use a custom branch of opam that uses [Z3] instead.
• I'm still meaning to add a revdeps counter soon as it is
especially
useful for new compiler releases (suggested by @bluddy a while
ago,
see previous post)
• Discuss and email integration, to send a message every time a
run
has finished (every 3-4 days). For now only Slack has just
been
integrated.
As OCaml 4.08 will be somewhat soon released, I'm inviting
everyone
(especially maintainers), with some spare time and will power,
to have
a look at the main page with those filters:
[Chase down non-available/broken opam packages for OCaml 4.08]
For maintainers you can filter yourself and get only the
packages you
are maintaining, using the form for this purpose.
Happy hunt.
/Side note: for now the diff page is going to show garbage data
due to
a server failure during the previous run/
[last month]
<https://discuss.ocaml.org/t/check-ocamllabs-io-new-features-and-call-to-rename/3373>
[check.ocamllabs.io] <http://check.ocamllabs.io>
[opam-health-check]
<https://github.com/kit-ty-kate/opam-health-check>
[SYMPHONY] <https://github.com/coin-or/SYMPHONY>
[Z3] <https://github.com/Z3Prover/z3>
[Chase down non-available/broken opam packages for OCaml 4.08]
<http://check.ocamllabs.io/?comp=4.07.1&comp=4.08.0+beta2&available=4.07.1&available=4.08.0+beta2&show-diff-only=true>
Turn echoing off on standard input to read e.g. passwords
═════════════════════════════════════════════════════════
Archive:
<https://sympa.inria.fr/sympa/arc/caml-list/2019-03/msg00064.html>
Helmut Brandl asked
───────────────────
Is there a portable way in ocaml to turn echoing off on standard
input
from the terminal to read e.g. passwords? By portable I mean
that it
works for Windows, Unix and Mac.
Matthew Ryan replied
────────────────────
The usual way to do this (for any language) is using ANSI escape
sequences. Code 8 sets the terminal to conceal characters and
code 0
resets the attributes, making them visible again.
For example, in a unix shell you can test this with echo and
read:
echo -e '\x1b[8m'; read varname; echo -e '\x1b[0m'
To do the same from OCaml, you can output "\x1b[8m", read the
password, and then output "\x1b[0m" afterwards to switch
printing back
on.
I believe that this will work on Windows 10, but earlier
versions may
not have the necessary ANSI support.
Daniel Bünzli also replied
──────────────────────────
Just for refence another way (that will in no way work on
Windows) is
to temporarily tweak the terminal attributes. The ocamlunix book
shows
how to do this [here][1].
In contrast to ANSI escapes which I believe is just a rendering
trick
that snippet will not allow to cut and paste the input password
to
recover it, whether that's a property you care about or not is
up to
your use case.
Best,
Daniel
[1]: <https://ocaml.github.io/ocamlunix/files.html#sec49>
Chet Murthy said
────────────────
A little Googling turns up that the author of the Unix library
(Xavier, IIRC) provided support for termios(3). So you can
already do
what you want in Ocaml with no extra C ugly bits.
Here's a little ocaml program to demonstrate, and after it, some
strace output showing the way it calls ioctl(2) to manipulate
the line
discipline (relevant bits bolded in HTML format mail).
┌────
│ let main () =
│ let open Unix in
│ let tios = tcgetattr stdin in
│ Printf.printf "c_echo: %b\n" tios.c_echo ;
│ Printf.printf "c_echoe: %b\n" tios.c_echoe ;
│ Printf.printf "c_echok: %b\n" tios.c_echok ;
│ Printf.printf "c_echonl: %b\n" tios.c_echonl ;
│ flush Pervasives.stdout ;
│ tios.c_echo <- false ;
│ tcsetattr stdin TCSANOW tios ;
│ let tios = tcgetattr stdin in
│ Printf.printf "AFTER c_echo: %b\nSleeping 10 sec ....\n"
tios.c_echo ;
│ flush Pervasives.stdout ;
│ Unix.sleep 10;
│ tios.c_echo <- true ;
│ tcsetattr stdin TCSANOW tios ;
│ ()
│ ;;
│
│ main() ;;
└────
┌────
│ $ strace -eioctl ./noecho
│ ioctl(0, TCGETS, {B38400 opost isig icanon echo ...}) = 0
│ c_echo: true
│ c_echoe: true
│ c_echok: true
│ c_echonl: false
│ ioctl(0, TCGETS, {B38400 opost isig icanon *echo* ...}) = 0
│ ioctl(0, TCGETS, {B38400 opost isig icanon *echo* ...}) = 0
│ ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon
*-echo *...})
│ = 0
│ ioctl(0, TCGETS, {B38400 opost isig icanon *-echo *...}) = 0
│ ioctl(0, TCGETS, {B38400 opost isig icanon *-echo* ...}) = 0
│ AFTER c_echo: false
│ Sleeping 10 sec ....
│ ioctl(0, TCGETS, {B38400 opost isig icanon *-echo* ...}) = 0
│ ioctl(0, TCGETS, {B38400 opost isig icanon *-echo* ...}) = 0
│ ioctl(0, SNDCTL_TMR_START or TCSETS, {B38400 opost isig icanon
*echo* ...})
│ = 0
│ ioctl(0, TCGETS, {B38400 opost isig icanon *echo* ...}) = 0
│ +++ exited with 0 +++
└────
Jeremie Dimino also replied
───────────────────────────
If you don't mind the extra dependency, there is a complete
example in
the lambda-term library:
<https://github.com/ocaml-community/lambda-term/blob/master/examples/read_password.ml>
The main differences with the other solutions mentioned in this
thread
are that this version works on Windows, supports line edition
and
supports customisation such as displaying nothing or displaying
stars.
http2/af: An HTTP/2 implementation for OCaml
════════════════════════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-http2-af-an-http-2-implementation-for-ocaml/3578/1>
Antonio Nuno Monteiro announced
───────────────────────────────
I'm pleased to announce the product of a few months of work: an
HTTP/2
implementation written entirely in OCaml: http2/af.
http2/af is based on the concepts in [http/af], using Angstrom
and
Faraday for the parsing and serialization of the HTTP/2 framing
layer,
respectively. It also preserves the same API as http/af wherever
possible, for familiarity reasons. The notable exception is the
addition of a `Reqd.push' function that implements the HTTP/2
[server
push] functionality.
http2/af currently provides a server implementation, as well as
runtime implementations for Lwt (UNIX) and Mirage (which I
implemented
at the last Mirage Hack Retreat in Marrakech).
The repo for http2/af is [here]. The packages are not yet
released to
OPAM, a task I'm planning to complete in the next few days.
Happy to hear any feedback / answer questions here or in Github
issues
(<https://github.com/anmonteiro/http2af/issues>).
[http/af] <https://github.com/inhabitedtype/httpaf/>
[server push]
<https://httpwg.org/specs/rfc7540.html#PushResources>
[here] <https://github.com/anmonteiro/http2af>
Antonio Nuno Monteiro later added
─────────────────────────────────
There were some licensing issues in this work related to
oversights
and ignorance on my part. I’m copying a text from a Reddit post
of
mine that tries to clarify the situation below.
Thanks everyone who brought all the licensing issues to my
attention.
To clarify: I never intended to “steal” any code, I.e. passing
work as
mine without proper attribution to the original authors. The
truth is
that, while I’ve been doing open source for a little while, this
is
the first time that I’ve done any derivative work, and not being
a
lawyer, I really had no idea what exactly I needed to do (my
thought
process being that if my code didn’t bear any resemblance at all
to
the original code then I wouldn’t need to preserve the copyright
headers).
It has been brought to my attention that I was wrong and I have
therefore rectified the situation.
To clarify further what h2 is in comparison to http/af: h2 is an
implementation of HTTP/2 (a totally different protocol) that
tries to
share the http/af types and API wherever possible. I understand
now
that this is derivative work because it shares the same
underlying
architecture, but I didn’t know that coming into it at first.
To all the affected parties: my apologies, I hope you can
forgive me.
Release of OCamlFormat 0.9
══════════════════════════
Archive:
<https://discuss.ocaml.org/t/ann-release-of-ocamlformat-0-9/3589/1>
Guillaume Petiot announced
──────────────────────────
*Release of OCamlFormat 0.9*
We are pleased to announce the release of OCamlFormat (available
on
opam). There have been numerous changes since the last release,
so
here is a comprehensive list of the new features and breaking
changes
to help the transition from OCamlFormat 0.8.
Dependencies
╌╌╌╌╌╌╌╌╌╌╌╌
OCamlFormat now requires:
• ocaml >= 4.05 (up from 4.04.1)
• dune >= 1.1.1
• octavius >= 1.2.0
• uutf
OCamlFormat_Reason now requires:
• ocaml >= 4.05
• dune >= 1.1.1
• ocaml-migrate-parsetree >= 1.0.10 (up from 1.0.6)
• octavius >= 1.2.0
• uutf
• reason >= 3.2.0 (up from 1.13.4)
New preset profiles
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The `ocamlformat' profile aims to take advantage of the
strengths of a
parsetree-based auto-formatter, and to limit the consequences of
the
weaknesses imposed by the current implementation. This is a
style
which optimizes for what the formatter can do best, rather than
to
match the style of any existing code.
General guidelines that have directed the design include:
• Legibility, in the sense of making it as hard as possible for
quick
visual parsing to give the wrong interpretation, is of highest
priority;
• Whenever possible the high-level structure of the code should
be
obvious by looking only at the left margin, in particular, it
should
not be necessary to visually jump from left to right hunting
for
critical keywords, tokens, etc;
• All else equal compact code is preferred as reading without
scrolling is easier, so indentation or white space is avoided
unless
it helps legibility;
• Attention has been given to making some syntactic gotchas
visually
obvious.
`ocamlformat' is the new default profile.
The `conventional' profile aims to be as familiar and
"conventional"
appearing as the available options allow.
The `default' profile is `ocamlformat' with `break-cases=fit'.
`default' is deprecated and will be removed in version 0.10.
OCamlFormat diff tool
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
`ocamlformat-diff' is a tool that uses OCamlFormat to apply the
same
formatting to compared OCaml files, so that the formatting
differences
between the two files are not displayed. Note that
`ocamlformat-diff'
comes in a separate opam package and is not included in the
`ocamlformat' package.
The file comparison is then performed by any diff backend.
The options' documentation is available through
`ocamlformat-diff
--help'.
The option `--diff' allows you to configure the diff command
that is
used to compare the formatted files. The default value is the
vanilla
`diff', but you can also use `patdiff' or any other similar
comparison
tool.
`ocamlformat-diff' can be integrated with `git diff', as
explained in
the [online documentation].
[online documentation]
<https://github.com/ocaml-ppx/ocamlformat/blob/master/tools/ocamlformat-diff/README.md>
Formatting docstrings
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Previously, the docstrings `(** This is a docstring *)' could
only be
formatted like regular comments, a new option
`--parse-docstrings' has
been added so that docstrings can be nicely formatted.
Here is a small example:
┌────
│ (** {1 Printers and escapes used by Cmdliner module} *)
│
│ val subst_vars : subst:(string -> string option) -> Buffer.t
-> string -> string
│ (** [subst b ~subst s], using [b], substitutes in [s]
variables of the form
│ "$(doc)" by their [subst] definition. This leaves escapes
and markup
│ directives $(markup,...) intact.
│ @raise Invalid_argument in case of illegal syntax. *)
└────
Note that this option is disabled by default and you have to set
it
manually by adding `--parse-docstrings' to your command line or
`parse-docstrings=true' to your `.ocamlformat' file. If you get
the
following error message:
Error: Formatting of (** … *) is unstable (e.g. parses as
a list or not depending on the margin), please tighten up
this comment in the source or disable the formatting using
the option –no-parse-docstrings.
It means the original docstring cannot be formatted (e.g.
because it
does not comply with the odoc syntax) and you have to edit it or
disable the formatting of docstrings.
Of course if you think your docstring complies with the odoc
syntax
and there might be a bug in OCamlFormat, [feel free to file an
issue
on github].
[feel free to file an issue on github]
<https://github.com/ocaml-ppx/ocamlformat/issues>
Print the configuration
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new `--print-config' flag prints the configuration
determined by
the environment variable, the configuration files, preset
profiles and
command line. Attributes are not considered.
It provides the full list of options with the values they are
set to,
and the source of this value. For example `ocamlformat
--print-config' prints:
┌────
│ profile=ocamlformat (file .ocamlformat:1)
│ quiet=false (profile ocamlformat (file .ocamlformat:1))
│ max-iters=10 (profile ocamlformat (file .ocamlformat:1))
│ comment-check=true (profile ocamlformat (file .ocamlformat:1))
│ wrap-fun-args=true (profile ocamlformat (file .ocamlformat:1))
│ wrap-comments=true (file .ocamlformat:5)
│ type-decl=compact (profile ocamlformat (file .ocamlformat:1))
│ space-around-collection-expressions=false (profile ocamlformat
(file .ocamlformat:1))
│ single-case=compact (profile ocamlformat (file
.ocamlformat:1))
│ sequence-style=separator (profile ocamlformat (file
.ocamlformat:1))
│ parse-docstrings=true (file .ocamlformat:4)
│ parens-tuple-patterns=multi-line-only (profile ocamlformat
(file .ocamlformat:1))
│ parens-tuple=always (profile ocamlformat (file
.ocamlformat:1))
│ parens-ite=false (profile ocamlformat (file .ocamlformat:1))
│ ocp-indent-compat=false (profile ocamlformat (file
.ocamlformat:1))
│ module-item-spacing=sparse (profile ocamlformat (file
.ocamlformat:1))
│ margin=77 (file .ocamlformat:3)
│ let-open=preserve (profile ocamlformat (file .ocamlformat:1))
│ let-binding-spacing=compact (profile ocamlformat (file
.ocamlformat:1))
│ let-and=compact (profile ocamlformat (file .ocamlformat:1))
│ leading-nested-match-parens=false (profile ocamlformat (file
.ocamlformat:1))
│ infix-precedence=indent (profile ocamlformat (file
.ocamlformat:1))
│ indicate-nested-or-patterns=space (profile ocamlformat (file
.ocamlformat:1))
│ indicate-multiline-delimiters=true (profile ocamlformat (file
.ocamlformat:1))
│ if-then-else=compact (profile ocamlformat (file
.ocamlformat:1))
│ field-space=tight (profile ocamlformat (file .ocamlformat:1))
│ extension-sugar=preserve (profile ocamlformat (file
.ocamlformat:1))
│ escape-strings=preserve (profile ocamlformat (file
.ocamlformat:1))
│ escape-chars=preserve (profile ocamlformat (file
.ocamlformat:1))
│ doc-comments-tag-only=default (profile ocamlformat (file
.ocamlformat:1))
│ doc-comments-padding=2 (profile ocamlformat (file
.ocamlformat:1))
│ doc-comments=after (profile ocamlformat (file .ocamlformat:1))
│ disable=false (profile ocamlformat (file .ocamlformat:1))
│ cases-exp-indent=4 (profile ocamlformat (file .ocamlformat:1))
│ break-struct=force (profile ocamlformat (file .ocamlformat:1))
│ break-string-literals=wrap (profile ocamlformat (file
.ocamlformat:1))
│ break-sequences=false (profile ocamlformat (file
.ocamlformat:1))
│ break-separators=before (profile ocamlformat (file
.ocamlformat:1))
│ break-infix-before-func=true (profile ocamlformat (file
.ocamlformat:1))
│ break-infix=wrap (profile ocamlformat (file .ocamlformat:1))
│ break-fun-decl=wrap (profile ocamlformat (file
.ocamlformat:1))
│ break-collection-expressions=fit-or-vertical (profile
ocamlformat (file .ocamlformat:1))
│ break-cases=fit (file .ocamlformat:2)
└────
If many input files are specified, only print the configuration
for
the first file. If no input file is specified, print the
configuration for the root directory if specified, or for the
current
working directory otherwise.
Parentheses around if-then-else branches
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
A new option `parens-ite' has been added to decide whether to
use
parentheses around if-then-else branches that spread across
multiple
lines.
If this option is set, the following function:
┌────
│ let rec loop count a =
│ if count >= self#len
│ then a
│ else
│ let a' = f cur#get count a in
│ cur#incr ();
│ loop (count + 1) a'
└────
will be formatted as:
┌────
│ let rec loop count a =
│ if count >= self#len
│ then a
│ else (
│ let a' = f cur#get count a in
│ cur#incr ();
│ loop (count + 1) a' )
└────
Parentheses around tuple patterns
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
A new option `parens-tuple-patterns' has been added, that mimics
`parens-tuple' but only applies to patterns, whereas
`parens-tuples'
only applies to expressions.
`parens-tuple-patterns=multi-line-only'
mode will try to skip parentheses for single-line tuple
patterns, this
is the default value. `parens-tuple-patterns=always' always
uses
parentheses around tuples patterns.
For example:
┌────
│ (* with parens-tuple-patterns=always *)
│ let (a, b) = (1, 2)
│
│ (* with parens-tuple-patterns=multi-line-only *)
│ let a, b = (1, 2)
└────
Single-case pattern-matching expressions
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `single-case' defines the style of
pattern-matching
expressions with only a single case. `single-case=compact' will
try
to format a single case on a single line, this is the default
value.
`single-case=sparse' will always break the line before a single
case.
For example:
┌────
│ (* with single-case=compact *)
│ try some_irrelevant_expression
│ with Undefined_recursive_module _ -> true
│
│ (* with single-case=sparse *)
│ try some_irrelevant_expression
│ with
│ | Undefined_recursive_module _ -> true
└────
Space around collection expressions
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `space-around-collection-expressions' decides
whether
to add a space inside the delimiters of collection expressions
(lists,
arrays, records).
For example:
┌────
│ (* by default *)
│ type wkind = {f : 'a. 'a tag -> 'a kind}
│ let l = ["Nil", TCnoarg Thd; "Cons", TCarg (Ttl Thd, tcons)]
│
│ (* with space-around-collection-expressions *)
│ type wkind = { f : 'a. 'a tag -> 'a kind }
│ let l = [ "Nil", TCnoarg Thd; "Cons", TCarg (Ttl Thd, tcons) ]
└────
Break separators
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `break-separators' decides whether to break
before or
after separators such as `;' in list or record expressions, `*'
in
tuples or `->' in arrow types. `break-separators=before' breaks
the
expressions before the separator, this is the default value.
`break-separators=after' breaks the expressions after the
separator.
`break-separators=after-and-docked' breaks the expressions after
the
separator and docks the brackets for records.
For example:
┌────
│ (* with break-separators=before *)
│ type t =
│ { foooooooooooooooooooooooo:
foooooooooooooooooooooooooooooooooooooooo
│ ; fooooooooooooooooooooooooooooo:
fooooooooooooooooooooooooooo }
│
│ (* with break-separators=after *)
│ type t =
│ { foooooooooooooooooooooooo:
foooooooooooooooooooooooooooooooooooooooo;
│ fooooooooooooooooooooooooooooo:
fooooooooooooooooooooooooooo }
│
│ (* with break-separators=after-and-docked *)
│ type t = {
│ foooooooooooooooooooooooo:
foooooooooooooooooooooooooooooooooooooooo;
│ fooooooooooooooooooooooooooooo: fooooooooooooooooooooooooooo
│ }
└────
Not breaking before bind/map operators
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `break-infix-before-func' decides whether to
break
infix operators whose right arguments are anonymous functions
specially. This option is set by default, if you disable it
with
`--no-break-infix-before-func', it will not break before the
operator
so that the first line of the function appears docked at the end
of
line after the operator.
For example:
┌────
│ (* by default *)
│ f x
│ >>= fun y ->
│ g y
│ >>= fun () ->
│ f x >>= fun y -> g y >>= fun () -> f x >>= fun y -> g y >>=
fun () -> y ()
│
│ (* with break-infix-before-func = false *)
│ f x >>= fun y ->
│ g y >>= fun () ->
│ f x >>= fun y -> g y >>= fun () -> f x >>= fun y -> g y >>=
fun () -> y ()
└────
Break toplevel cases
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
There is a new value for the `break-cases' option: `toplevel',
that
forces top-level cases (i.e. not nested or-patterns) to break
across
lines, otherwise breaks naturally at the margin.
For example:
┌────
│ let f =
│ let g = function
│ | H when x y <> k -> 2
│ | T | P | U -> 3
│ in
│ fun x g t h y u ->
│ match x with
│ | E -> 4
│ | Z | P | M -> (
│ match y with
│ | O -> 5
│ | P when h x -> (
│ function
│ | A -> 6 ) )
└────
Number of spaces before docstrings
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `doc-comments-padding' controls how many spaces
are
printed before doc comments in type declarations. The default
value
is 2.
For example:
┌────
│ (* with doc-comments-padding = 2 *)
│ type t = {a: int (** a *); b: int (** b *)}
│
│ (* with doc-comments-padding = 1 *)
│ type t = {a: int (** a *); b: int (** b *)}
└────
Ignore files
╌╌╌╌╌╌╌╌╌╌╌╌
An `.ocamlformat-ignore' file specifies files that OCamlFormat
should
ignore. Each line in an `.ocamlformat-ignore' file specifies a
filename relative to the directory containing the
`.ocamlformat-ignore' file. Lines starting with `#' are ignored
and
can be used as comments.
Here is an example of such `.ocamlformat-ignore' file:
┌────
│ #This is a comment
│ dir2/ignore_1.ml
└────
Tag-only docstrings
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `doc-comments-tag-only' controls the position of
doc
comments only containing tags. `doc-comments-tag-only=default'
means
no special treatment is done, this is the default value.
`doc-comments-tag-only=fit' puts doc comments on the same line
if it
fits.
For example:
┌────
│ (* with doc-comments-tag-only = default *)
│
│ (** @deprecated *)
│ open Module
│
│ (* with doc-comments-tag-only = fit *)
│
│ open Module (** @deprecated *)
└────
Fit or vertical mode for if-then-else
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
There is a new value for the option `if-then-else':
`fit-or-vertical'.
`fit-or-vertical' vertically breaks all branches if they do not
fit on
a single line. Compared to the `compact' (default) value, it
breaks
all branches if at least one of them does not fit on a single
line.
For example:
┌────
│ (* with if-then-else = compact *)
│ let _ =
│ if foo then
│ let a = 1 in
│ let b = 2 in
│ a + b
│ else if foo then 12
│ else 0
│
│ (* with if-then-else = fit-or-vertical *)
│ let _ =
│ if foo then
│ let a = 1 in
│ let b = 2 in
│ a + b
│ else if foo then
│ 12
│ else
│ 0
└────
Check mode
╌╌╌╌╌╌╌╌╌╌
A new `--check' flag has been added. It checks whether the
input
files already are formatted. This flag is mutually exclusive
with
`--inplace' and `--output'. It returns `0' if the input files
are
indeed already formatted, or `1' otherwise.
Break function declarations
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
The new option `break-fun-decl' controls the style for function
declarations and types. `break-fun-decl=wrap' breaks only if
necessary, this is the default value.
`break-fun-decl=fit-or-vertical' vertically breaks arguments if
they
do not fit on a single line. `break-fun-decl=smart' is like
`fit-or-vertical' but try to fit arguments on their line if they
fit.
The `wrap-fun-args' option now only controls the style for
function
calls, and no more for function declarations.
For example:
┌────
│ (* with break-fun-decl = wrap *)
│ let ffffffffffffffffffff aaaaaaaaaaaaaaaaaaaaaa
bbbbbbbbbbbbbbbbbbbbbb
│ cccccccccccccccccccccc =
│ g
│
│ (* with break-fun-decl = fit-or-vertical *)
│ let ffffffffffffffffffff
│ aaaaaaaaaaaaaaaaaaaaaa
│ bbbbbbbbbbbbbbbbbbbbbb
│ cccccccccccccccccccccc =
│ g
│
│ (* with break-fun-decl = smart *)
│ let ffffffffffffffffffff
│ aaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbb
cccccccccccccccccccccc =
│ g
└────
Disable configuration in files and attributes
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
Two new options have been added so that `.ocamlformat'
configuration
files and attributes in OCaml files do not change the
configuration.
These options can be useful if you use some preset profile and
you do
not want attributes and `.ocamlformat' files to interfere with
your
preset configuration. `--disable-conf-attrs' disables the
configuration in attributes, and `--disable-conf-files' disables
`.ocamlformat' configuration files.
Preserve module items spacing
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
There is a new value for the option `module-item-spacing':
`preserve',
that will not leave open lines between one-liners of similar
sorts
unless there is an open line in the input.
For example the line breaks are preserved in the following code:
┌────
│ let cmos_rtc_seconds = 0x00
│ let cmos_rtc_seconds_alarm = 0x01
│ let cmos_rtc_minutes = 0x02
│
│ let x = o
│
│ let log_other = 0x000001
│ let log_cpu = 0x000002
│ let log_fpu = 0x000004
└────
Breaking changes
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• When `--disable-outside-detected-project' is set, disable
ocamlformat when no `.ocamlformat' file is found.
• Files are not parsed when ocamlformat is disabled.
• Disallow `-' with other input files.
• The `wrap-fun-args' option now only controls the style for
function
calls, and no more for function declarations.
• The default profile is now named `ocamlformat'.
• The deprecated syntax for `.ocamlformat' files: `option value'
is no
more supported anymore and you should use the `option = value'
syntax instead.
Miscellaneous bugfixes
╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌╌
• Preserve shebang (e.g. `#!/usr/bin/env ocaml') at the
beginning of a
file.
• Improve the formatting when `ocp-indent-compat' is set.
• UTF8 characters are now correctly printed in comments.
• Add parentheses around a constrained any-pattern (e.g. `let (_
:
int) = x1').
• Emacs: the temporary buffer is now killed.
• Emacs: add the keybinding in tuareg's map instead of merlin's.
• Lots of improvements on the comments, docstrings, attributes
formatting.
• Lots of improvements on the formatting of modules.
• Lots of improvements in the Reason support.
• Do not rely on the file-system to format sources.
• The `--debug' mode is more user-friendly.
Credits
╌╌╌╌╌╌╌
This release also contains many other changes and bug fixes that
we
cannot detail here.
Special thanks to our maintainers and contributors for this
release:
Jules Aguillon, Mathieu Barbin, Josh Berdine, Jérémie Dimino,
Hugo
Heuzard, Ludwig Pacifici, Guillaume Petiot, Nathan Rebours and
Louis
Roché.
If you wish to get involved with OCamlFormat development or file
an
issue, please read the [contributing guide], any contribution is
welcomed.
[contributing guide]
<https://github.com/ocaml-ppx/ocamlformat/blob/master/CONTRIBUTING.md>
Other OCaml News
════════════════
From the ocamlcore planet blog
──────────────────────────────
Here are links from many OCaml blogs aggregated at [OCaml
Planet].
• [OCaml on Baremetal Shakti RISC-V processor]
• [Release of OCamlFormat 0.9]
[OCaml Planet] <http://ocaml.org/community/planet/>
[OCaml on Baremetal Shakti RISC-V processor]
<http://kcsrk.info/ocaml/riscv/shakti/2019/03/29/1400-ocaml-baremetal-shakti/>
[Release of OCamlFormat 0.9]
<https://tarides.com/blog/2019-03-29-release-of-ocamlformat-0-9.html>
Old CWN
═══════
If you happen to miss a CWN, you can [send me a message] and
I'll mail
it to you, or go take a look at [the archive] or the [RSS feed
of the
archives].
If you also wish to receive it every week by mail, you may
subscribe
[online].
[Alan Schmitt]
[send me a message] <mailto:alan.schmitt at polytechnique.org>
[the archive] <http://alan.petitepomme.net/cwn/>
[RSS feed of the archives]
<http://alan.petitepomme.net/cwn/cwn.rss>
[online] <http://lists.idyll.org/listinfo/caml-news-weekly/>
[Alan Schmitt] <http://alan.petitepomme.net/>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190402/7e4ddc47/attachment-0001.html>
-------------- next part --------------
A non-text attachment was scrubbed...
Name: not available
Type: application/pgp-signature
Size: 487 bytes
Desc: not available
URL: <http://lists.idyll.org/pipermail/caml-news-weekly/attachments/20190402/7e4ddc47/attachment-0001.pgp>
More information about the caml-news-weekly
mailing list