messagetemplates / messagetemplates-fsharp

Message templates - the ability to format named string values, and capture the properties
http://messagetemplates.org/
Apache License 2.0
18 stars 4 forks source link

Take advantage of `ICustomFormatter` or `IFormattable` when an object with default destructuring #23

Open lust4life opened 6 years ago

lust4life commented 6 years ago

Change scalarStringCatchAllDestr to catch the original scalar object, then format properly when writePropValue.

e.g.

type User = 
  {
    id      : int 
    name    : string
    created : DateTime
  }
with
  interface IFormattable with
    member x.ToString (format, provider) =
      sprintf "id => %i, name => %s, created => %s" x.id x.name (x.created.ToShortDateString())

let foo = { id = 999; name = "foo"; created = DateTime.Now}
let nl = Environment.NewLine + Environment.NewLine

Formatting.format (Parser.parse "{default} {nl} {$stringify} {nl} {@capture}") [| foo; nl; foo; nl; foo; |] 
System.String.Format("{0}",foo)

before:

> Formatting.format (Parser.parse "{default} {nl} {$stringify} {nl} {@capture}") [| foo; nl; foo; nl; foo; |]
- ;;
val it : string =
  ""{id = 999;
 name = \"foo\";
 created = 11/3/2017 7:49:41 PM;}" "

" "{id = 999;
 name = \"foo\";
 created = 11/3/2017 7:49:41 PM;}" "

" User { id: 999, name: "foo", created: 11/3/2017 7:49:41 PM }"

> System.String.Format("{0}",foo)
- ;;
val it : string = "id => 999, name => foo, created => 11/3/2017"

after:

> Formatting.format (Parser.parse "{default} {nl} {$stringify} {nl} {@capture}") [| foo; nl; foo; nl; foo; |]
val it : string =
  "id => 999, name => foo, created => 11/3/2017"

" "{id = 999;
 name = \"foo\";
 created = 11/3/2017 7:40:16 PM;}" "

" User { id: 999, name: "foo", created: 11/3/2017 7:40:16 PM }"

> System.String.Format("{0}",foo)
val it : string = "id => 999, name => foo, created => 11/3/2017"
lust4life commented 6 years ago

an object with default destructuring is rendered as a string literal

Is this still true even with support custom format ?

adamchester commented 6 years ago

Hi @lust4life sorry I haven't got to this yet, I'll try to look in the next few days :+1: Thanks!

lust4life commented 6 years ago

@adamchester 😃 , ok , take your time. i will ping you after few days.

lust4life commented 6 years ago

@adamchester do we need consider replace "\n" with "\\n" , when write as string ? right now , we just deal with ". if we also deal with newline, in most case, the output can be just one line string.

type User = 
  {
    id      : int 
    name    : string
    created : DateTime
  }
let foo = { id = 999; name = "foo"; created = DateTime.Now}
Formatting.format (Parser.parse "stringify is: {$foo} and destructure is: {@capture}") [| foo; foo |] 

right now:

val it : string =
  "stringify is: "{id = 999;
 name = \"foo\";
 created = 11/18/2017 2:37:46 PM;}" and destructure is: User { id: 999, name: "foo", created: 11/18/2017 2:37:46 PM }"

replaced:

val it : string =
  "stringify is: "{id = 999;\n name = \"foo\";\n created = 11/18/2017 2:43:30 PM;}" and destructure is: User { id: 999, name: "foo", created: 11/18/2017 2:43:30 PM }"

if user want to keep newline as it was, they can add l as its format.

Formatting.format (Parser.parse "stringify is: {$foo:l} and destructure is: {@capture}") [| foo; foo |] 

val it : string =
  "stringify is: {id = 999;
 name = "foo";
 created = 11/18/2017 2:37:46 PM;} and destructure is: User { id: 999, name: "foo", created: 11/18/2017 2:37:46 PM }"
lust4life commented 6 years ago

after that, things become as:

adamchester commented 6 years ago

Hey @lust4life!

do we need consider replace "\n" with "\n" , when write as string ?

Can you please elaborate on why replacing newlines would be better?

lust4life commented 6 years ago

want to use messagetemplates to format Event message in Logary (maybe next version), seems levelDatetimeMessagePathNewLine did not want to show some newline in message template (the body part), one line will be more conducive to the format unification.

But it's not necessary, it's just a temporary thought and can be done in logary itself. What i really want here is: change scalarStringCatchAllDestr to catch the original scalar object, this will support custom format.

lust4life commented 6 years ago

and should we support Map here isScalarDict ?