GithubHelp home page GithubHelp logo

fmt's People

Contributors

dbuenzli avatar drup avatar edwintorok avatar hcarty avatar misterda avatar pqwy avatar rizo avatar talex5 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

fmt's Issues

Fmt.invalid_arg should type error?

This does not cause a type error:

Fmt.invalid_arg "hello" 1

Is this expected? Fmt.pr shows a type error as I would expect:

# Fmt.pr "hello" 1;;
Error: This expression has type
         ('a -> 'b, Format.formatter, unit, unit, unit, 'a -> 'b)
         CamlinternalFormatBasics.fmt
       but an expression was expected of type
         ('a -> 'b, Format.formatter, unit, unit, unit, unit)
         CamlinternalFormatBasics.fmt
       Type 'a -> 'b is not compatible with type unit

Change the name `Fmt.pp`

When you have a recursive datastructure and you want to define a pretty printer for it (that you naturally call 'pp'), you end up with code like that:

let rec pp : t Fmt.t = fun fmt -> function
  | Mod d          -> Fmt.string fmt d#module_name
  | List (f, args) ->
    Fmt.pp fmt "%s%a"
      f#module_name
      Fmt.(parens @@ list pp) args

and then the last line is wrong, because of the local open.

I'm afraid the situation is going to be quite frequent. A name different than pp would probably be better ...

Fmt.kstrf doesn't like partial application

The following program gives an assert failure:

let parse fmt = Fmt.kstrf (fun x -> x) fmt

let check f = assert (f "X" = f "X")

let () = check (parse "%s")

This is fixed if you replace Fmt.kstrf by Format.ksprintf. This is fixed if you eta-expand (parse "%s") into (fun x -> parse "%s" x). Not sure exactly what is happening there ...

fmt fails to build with 4.14.0+trunk

I get the following error log when I try to build fmt with 4.14.0+trunk and dune.2.9.0

#=== ERROR while compiling fmt.0.8.9 ==========================================#
# context     2.0.8 | linux/x86_64 | ocaml-variants.4.14.0+trunk | https://opam.ocaml.org#1fc79772
# path        ~/.opam/4.14.0+trunk/.opam-switch/build/fmt.0.8.9
# command     ~/.opam/opam-init/hooks/sandbox.sh build ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner false
# exit-code   1
# env-file    ~/.opam/log/fmt-2323173-d2c37b.env
# output-file ~/.opam/log/fmt-2323173-d2c37b.out
### output ###
# [...]
# 7 | let () = ignore (Toploop.use_file Format.err_formatter "fmt_tty_top_init.ml")
#                      ^^^^^^^^^^^^^^^^
# Error: Unbound value Toploop.use_file
# Command exited with code 2.
# pkg.ml: [ERROR] cmd ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-j' '4' '-tag' 'debug'
#      '-build-dir' '_build' 'opam' 'pkg/META' 'CHANGES.md' 'LICENSE.md'
#      'README.md' 'src/fmt.a' 'src/fmt.cmxs' 'src/fmt.cmxa' 'src/fmt.cma'
#      'src/fmt.cmx' 'src/fmt.cmi' 'src/fmt.mli' 'src/fmt_tty.a'
#      'src/fmt_tty.cmxs' 'src/fmt_tty.cmxa' 'src/fmt_tty.cma'
#      'src/fmt_tty.cmx' 'src/fmt_tty.cmi' 'src/fmt_tty.mli' 'src/fmt_top.a'
#      'src/fmt_top.cmxs' 'src/fmt_top.cmxa' 'src/fmt_top.cma'
#      'src/fmt_top.cmx' 'src/fmt_tty_top_init.ml']: exited with 10

Fmt.exn

Printexc.to_string and Printexc.raw_backtrace_to_string in combination with Fmt.lines can already be used to perform this, but may be convenient if Fmt already provided this.
The exception message could also be optionally highlighted with a Fmt.style (e.g. bold).

Add Fmt.{invalid_arg,failwith}

Raising the corresponding exceptions.

val Fmt.failwith : ('a, Format.formatter, unit, unit) format4 -> 'a
val Fmt.invalid_arg : ('a, Format.formatter, unit, unit) format4 -> 'a

Generalization of const's type and value restriction

Hi,
I remarked some of my code breaks due to the generalization of const's type as writing something such as:

let t = const string "t"

will yield a weak type variable in t's type.
Granted, in the case of my code, I should anyway have created an interface to fix the type of my functions (and this is what I'm gonna do) but I thought you may be interested in this piece of information. I'm not sure what outcome you expect of generalizing const's type compared to keeping unit in it?

The type of Fmt.unit is wrong

It is:

val unit : (unit, Format.formatter, unit) Pervasives.format -> unit t

Which prevents for example to write:

Fmt.(option (prefix (unit " ") pp_type)) 

It should be

val unit : string -> unit t

Styled formatting is not flexible

Currently, styled formatting is done by (conditionally) outputting terminal escape sequences. This means that there are two choices currently:

  • Output on something that understand escape sequences and enable styling
  • Do not style at all.

However, using Format.tag, it is possible to have customizable interpretation depending on the output formatter (one being escape sequence).
The upside is that it could output styled things on various outputs (html, lambda_term, etc), given the correct interpretation of tags (which doesn't need to be provided in fmt).
The downside is that enabling styling must be done for each output formatter.

It's something I did for lambda_term once. The implementation was a bit awkward but the interface ended up being rather simple (one pp function, like you have currently).

Add Fmt.{print_endline, prerr_endline}

What do you think of adding

val Fmt.print_endline : ('a, Format.formatter, unit, unit) format4 -> 'a
val Fmt.print_endline : ('a, Format.formatter, unit, unit) format4 -> 'a

implemented as

let print_endline fmt = kstrf print_endline fmt
let prerr_endline fmt = kstrf prerr_endline fmt

potentially with better names.

I end up using these often in toplevel sessions and small throw-away scripts/programs when setting up Logs may be more code than it's worth.

The git repository is missing the v0.9.0 tag

Before I start let me thank you for maintaining fmt. Just as a lot of other OCaml developers, I use it quite extensively!

fmt.0.9.0 has been released but it seems the corresponding git tag was not pushed either here or upstream at https://erratique.ch/repos/fmt.git. Could you please push the tag or eventually let me know the hash of the commit used to produce the release tarball?

To give you a bit of context, the reason why I'm asking for this is because we maintain dune ports of opam packages at https://github.com/dune-universe/opam-overlays to make them compatible with opam-monorepo. We want to make sure the dune ports are as close as possible to released version they correspond to.

Please let me know if I can help in any way with this.

Fmt.styled gets slower over time

I've been investigating a problem with my programs slowing down over time, but only when logging is configured. The problem seems to be with fmt (0.8.10)!

With this test program:

let n = 10000

let () =
  while true do
    let t0 = Unix.gettimeofday () in
    for _i = 1 to n do
      ignore @@ Fmt.str "Hello %a" Fmt.(styled `Blue string) "world"
    done;
    let t1 = Unix.gettimeofday () in
    Printf.printf "Formatted %.0f messages/second\n%!" (float n /. (t1 -. t0))
  done

I get:

$ dune exec -- ./test.exe
Formatted 522518 messages/second
Formatted 411017 messages/second
Formatted 298257 messages/second
Formatted 215499 messages/second
Formatted 155861 messages/second
Formatted 110564 messages/second
Formatted 77171 messages/second
Formatted 54181 messages/second
Formatted 37493 messages/second
Formatted 25499 messages/second
Formatted 17254 messages/second

Replacing Fmt.(styled `Blue string) with Fmt.string shows no slow-down.

Fmt.styled doesn't return a formatter of the same type

According to the documentation, applying Fmt.styled to a formatter returns one of the same type :

val styled : style -> 'a t -> 'a t
styled s pp formats like pp but styled with s.

but in practice, the 'a is replaced by unit :

Format.formatter ->
('a, Format.formatter, unit, unit, unit, unit) format6 -> 'a

becomes

Format.formatter ->
(unit, Format.formatter, unit, unit, unit, unit) format6 -> unit

and is thus only usable with simple strings.

Here is an example I would expect to work but doesn't :

Fmt.set_style_renderer  Fmt.stdout `Ansi_tty;

let pf = Fmt.pf in
pf Fmt.stdout "Hello, %s\n" "World";
let pf = Fmt.styled `Red pf  in
pf Fmt.stdout "Hello, %s\n" "World"

I had the same behaviour on OCaml 4.08.1 & 4.14.0

Add Fmt.nl

What do you think about this small newline format combinator?

let nl = Format.pp_print_newline

Which can be used like this:

# Fmt.(pr "%a" (list ~sep:nl int) [1; 2; 3])
1
2
3

Unable to compile on 32bit machine

ocaml-fmt-0.8.7, broken build on i586:
ocamlfind ocamldep -modules src/fmt.ml > src/fmt.ml.depends
ocamlfind ocamldep -modules src/fmt.mli > src/fmt.mli.depends
ocamlfind ocamlc -c -g -bin-annot -safe-string -I src -I test -o src/fmt.cmi src/fmt.mli
ocamlfind ocamlopt -c -g -bin-annot -safe-string -I src -I test -o src/fmt.cmx src/fmt.ml

  • ocamlfind ocamlopt -c -g -bin-annot -safe-string -I src -I test -o src/fmt.cmx src/fmt.ml
    File "src/fmt.ml", line 453, characters 2-12:
    453 | 0xffffffff, fmt "%08x"; ]
    ^^^^^^^^^^
    Error: Integer literal exceeds the range of representable integers of type int
    Command exited with code 2.

Error,Bug in Install fmt!

$ opam install fmt

The following actions will be performed:
  ∗  install fmt 0.8.2

=-=- Gathering sources =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[fmt] Archive in cache

=-=- Processing actions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[ERROR] The compilation of fmt failed at "ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner true".

#=== ERROR while installing fmt.0.8.2 =========================================#
# opam-version 1.2.2
# os           linux
# command      ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner true
# path         /home/guest/.opam/system/build/fmt.0.8.2
# compiler     system (4.02.3)
# exit-code    1
# env-file     /home/guest/.opam/system/build/fmt.0.8.2/fmt-17344-6d07ae.env
# stdout-file  /home/guest/.opam/system/build/fmt.0.8.2/fmt-17344-6d07ae.out
# stderr-file  /home/guest/.opam/system/build/fmt.0.8.2/fmt-17344-6d07ae.err
### stderr ###
# pkg.ml: [ERROR] key --dev-pkg: Unknown key.



=-=- Error report -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The following actions failed
  ∗  install fmt 0.8.2
No changes have been performed

$ opam install base-unix cmdliner fmt

[NOTE] Package base-unix is already installed (current version is base).
[NOTE] Package cmdliner is already installed (current version is 1.0.0).
The following actions will be performed:
  ∗  install fmt 0.8.2
Do you want to continue ? [Y/n] y

=-=- Gathering sources =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[fmt] Archive in cache

=-=- Processing actions -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
[ERROR] The compilation of fmt failed at "ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner true".

#=== ERROR while installing fmt.0.8.2 =========================================#
# opam-version 1.2.2
# os           linux
# command      ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner true
# path         /home/guest/.opam/system/build/fmt.0.8.2
# compiler     system (4.02.3)
# exit-code    1
# env-file     /home/guest/.opam/system/build/fmt.0.8.2/fmt-17402-6d07ae.env
# stdout-file  /home/guest/.opam/system/build/fmt.0.8.2/fmt-17402-6d07ae.out
# stderr-file  /home/guest/.opam/system/build/fmt.0.8.2/fmt-17402-6d07ae.err
### stderr ###
# pkg.ml: [ERROR] key --dev-pkg: Unknown key.



=-=- Error report -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
The following actions failed
  ∗  install fmt 0.8.2
No changes have been performed

how fix ?

Some documentation typos (file fmt.mli)

L088 : /int32/uint32/
L106 : /pp_float_dsig/float_dsig/
L209 : /botttom/bottom/
L241 : /brackets/braces/
L246 : /pp_text/text/
L250 : /pp_lines/lines/
L277 : /pp_byte_size/byte_size/
L282 : /pp_bi_byte_size/bi_byte_size/

Fmt.exn_backtrace crashes when backtraces are off

If compiled without debug symbols or run without OCAMLRUNPARAM=b, Printexc.raw_backtrace_to_string returns the empty string. Fmt.exn_backtrace then crashes with exception Invalid_argument("index out of bounds").

Also, if backtraces are on then it loses the last character of the error message. e.g.

let test_bt () =
  try failwith "Test"
  with ex ->
    let bt = Printexc.get_raw_backtrace () in
    Fmt.pr "[%s]@." (Printexc.raw_backtrace_to_string bt);
    let msg = Fmt.strf "%a" Fmt.exn_backtrace (ex, bt) in
    print_endline msg

prints

[Raised at file "pervasives.ml", line 32, characters 17-33
Called from file "test/test.ml", line 36, characters 6-21
]
Exception: Failure("Test")
Raised at file "pervasives.ml", line 32, characters 17-33
Called from file "test/test.ml", line 36, characters 6-2

(tested with OCaml 4.04.0)

Question on howto use "fmt"

(I'm a ocaml newbie)
I try to test the "fmt" module and ran into a problem. While "pam install fmt" seems to succeed, I cannot load it open Fmt;; : Error: Unbound module Fmt.
I tried to run the test/test.ml example but I dont really know howto compile it.

$ocamlc test.ml 
File "test.ml", line 23, characters 34-48:
Error: Unbound module Fmt

Add Fmt.Dump.uchar

to cater for the future removal of Uchar.dump and the lack of support by the dev team for such a formatter in the stdlib.

See discussion in ocaml/ocaml#1081

ERROR while compiling fmt.0.8.7

I want to try out Lucas Pluvinags’s mirage port to ESP32.
(https://www.lortex.org/posts/mirage/esp32/2018/06/22/build-your-own-mirage.html)

After creating and changing to a opam switch 4.06.0+32bit I want to do a
opam install mirage

which fails with:

> 
> <><> Processing actions <><><><><><><><><><><><><><><><><><><><><><><><>  <><><><>
> [ERROR] The compilation of fmt failed at
>     "/home/florian/.opam/opam-init/hooks/sandbox.sh build ocaml pkg/pkg.ml
>     build --dev-pkg false --with-base-unix true --with-cmdliner true".
> 
> #=== ERROR while compiling fmt.0.8.7 ==========================================#
> # context     2.0.4 | linux/x86_64 | ocaml-variants.4.06.0+32bit | https://opam.ocaml.org#3389beb3
> # path        ~/.opam/4.06.0+32bit/.opam-switch/build/fmt.0.8.7
> # command     ~/.opam/opam-init/hooks/sandbox.sh build ocaml pkg/pkg.ml build --dev-pkg false --with-base-unix true --with-cmdliner true
> # exit-code   1
> # env-file    ~/.opam/log/fmt-24744-6ef1df.env
> # output-file ~/.opam/log/fmt-24744-6ef1df.out
> ### output ###
> # [...]
> # Error: Integer literal exceeds the range of representable integers of type int
> # Command exited with code 2.
> # pkg.ml: [ERROR] cmd ['ocamlbuild' '-use-ocamlfind' '-classic-display' '-j' '4' '-tag' 'debug'
> #      '-build-dir' '_build' 'opam' 'pkg/META' 'CHANGES.md' 'LICENSE.md'
> #      'README.md' 'src/fmt.a' 'src/fmt.cmxs' 'src/fmt.cmxa' 'src/fmt.cma'
> #      'src/fmt.cmx' 'src/fmt.cmi' 'src/fmt.mli' 'src/fmt_tty.a'
> #      'src/fmt_tty.cmxs' 'src/fmt_tty.cmxa' 'src/fmt_tty.cma'
> #      'src/fmt_tty.cmx' 'src/fmt_tty.cmi' 'src/fmt_tty.mli' 'src/fmt_cli.a'
> #      'src/fmt_cli.cmxs' 'src/fmt_cli.cmxa' 'src/fmt_cli.cma'
> #      'src/fmt_cli.cmx' 'src/fmt_cli.cmi' 'src/fmt_cli.mli' 'src/fmt_top.a'
> #      'src/fmt_top.cmxs' 'src/fmt_top.cmxa' 'src/fmt_top.cma'
> #      'src/fmt_top.cmx' 'src/fmt_tty_top_init.ml']: exited with 10
> <><> Error report <><><><><><><><><><><><><><><><><><><><><><><><><><><><><><><>
> ┌─ The following actions failed
> │ λ build fmt 0.8.7
> └─ 
> ╶─ No changes have been performed
> 

Consider dropping the unix dependency

As far as I can see, Fmt only depends on unix for its isatty feature.
The ocaml runtime has caml_sys_isatty which is what you want. It is used in the compiler but not exported in the Stdlib. Maybe it should.

Adapt `fmt_top_init.ml` for `Omod`

# Omod.load "fmt";;
[INC] /Users/dbuenzli/.opam/4.03.0/lib/ocaml
[INC] /Users/dbuenzli/.opam/4.03.0/lib/result
[INC] /Users/dbuenzli/.opam/4.03.0/lib/fmt
[OBJ] /Users/dbuenzli/.opam/4.03.0/lib/fmt/fmt.cma
[SRC] /Users/dbuenzli/.opam/4.03.0/lib/fmt/fmt_top_init.ml
[ERROR] load /Users/dbuenzli/.opam/4.03.0/lib/fmt/fmt_top_init.ml:
File "/Users/dbuenzli/.opam/4.03.0/lib/fmt/fmt_top_init.ml", line 1:
Error: Reference to undefined global `Fmt_tty'

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.