Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rpc: serialize user message styles #8516

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions doc/changes/8516.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
- RPC message styles are now serialised meaning that RPC diagnostics keep their Ansi
styling. (#8516, fixes #6921, @Alizter)
2 changes: 2 additions & 0 deletions otherlibs/dune-rpc/dune_rpc.ml
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ module V1 = struct
module Message = Message
module Where = Where
module Registry = Registry
module Ansi_color = Ansi_color
module User_message = User_message
include Public

module Client = struct
Expand Down
97 changes: 97 additions & 0 deletions otherlibs/dune-rpc/dune_rpc.mli
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,101 @@ module V1 : sig
val to_string_absolute : t -> string
end

module Ansi_color : sig
module RGB8 : sig
(** 8-bit RGB color *)
type t

(** [to_int t] returns the 8-bit color as an integer in the range [0, 255]. *)
val to_int : t -> int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't think these functions are very useful. What about accessors like red, green, blue?

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It's not possible to do split into red, green and blue like we do for 24-bit color since not every terminal encodes 8-bit colors in the same manner. The only thing that doesn't change is that there are 256 colors.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The only time this can happen is if Dune runs a program with 8-bit color output and we wish to preserve that color. At that point we are at the mercy of the client on how we quantize those values.

end

module RGB24 : sig
(** 24-bit RGB color (true color) *)
type t

(** [red t] returns the red component of the 24-bit color [t]. *)
val red : t -> int

(** [green t] returns the green component of the 24-bit color [t]. *)
val green : t -> int

(** [blue t] returns the blue component of the 24-bit color [t]. *)
val blue : t -> int

(** [to_int t] returns the 24-bit color as an integer in the range [0, 0xFFFFFF].
Each color components consists of 8 bits. *)
val to_int : t -> int
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If I'm making a web client for viewing RPC messages, this might be a useful value to have since colors are hex values usually. (As an example of how this might be useful).

end

module Style : sig
(** Ansi Terminal Styles *)
type t =
[ `Fg_default
| `Fg_black
| `Fg_red
| `Fg_green
| `Fg_yellow
| `Fg_blue
| `Fg_magenta
| `Fg_cyan
| `Fg_white
| `Fg_bright_black
| `Fg_bright_red
| `Fg_bright_green
| `Fg_bright_yellow
| `Fg_bright_blue
| `Fg_bright_magenta
| `Fg_bright_cyan
| `Fg_bright_white
| `Fg_8_bit_color of RGB8.t
| `Fg_24_bit_color of RGB24.t
| `Bg_default
| `Bg_black
| `Bg_red
| `Bg_green
| `Bg_yellow
| `Bg_blue
| `Bg_magenta
| `Bg_cyan
| `Bg_white
| `Bg_bright_black
| `Bg_bright_red
| `Bg_bright_green
| `Bg_bright_yellow
| `Bg_bright_blue
| `Bg_bright_magenta
| `Bg_bright_cyan
| `Bg_bright_white
| `Bg_8_bit_color of RGB8.t
| `Bg_24_bit_color of RGB24.t
| `Bold
| `Dim
| `Italic
| `Underline
]
end
end

module User_message : sig
(** User Message Styles *)
module Style : sig
type t =
| Loc
| Error
| Warning
| Kwd
| Id
| Prompt
| Hint
| Details
| Ok
| Debug
| Success
| Ansi_styles of Ansi_color.Style.t list
end
end

module Target : sig
type t =
| Path of string
Expand Down Expand Up @@ -121,6 +216,7 @@ module V1 : sig

val loc : t -> Loc.t
val message : t -> unit Pp.t
val message_with_style : t -> User_message.Style.t Pp.t
end

type t
Expand All @@ -129,6 +225,7 @@ module V1 : sig
val loc : t -> Loc.t option
val id : t -> Id.t
val message : t -> unit Pp.t
val message_with_style : t -> User_message.Style.t Pp.t
val severity : t -> severity option
val promotion : t -> Promotion.t list

Expand Down
118 changes: 118 additions & 0 deletions otherlibs/dune-rpc/private/diagnostics_v1.ml
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
open Import
open Exported_types

module Related = struct
type t =
{ message : unit Pp.t
; loc : Loc.t
}

let sexp =
let open Conv in
let loc = field "loc" (required Loc.sexp) in
let message = field "message" (required sexp_pp_unit) in
let to_ (loc, message) = { loc; message } in
let from { loc; message } = loc, message in
iso (record (both loc message)) to_ from
;;

let to_diagnostic_related t : Diagnostic.Related.t =
{ message = t.message |> Pp.map_tags ~f:(fun _ -> User_message.Style.Details)
; loc = t.loc
}
;;

let of_diagnostic_related (t : Diagnostic.Related.t) =
{ message = t.message |> Pp.map_tags ~f:(fun _ -> ()); loc = t.loc }
;;
end

type t =
{ targets : Target.t list
; id : Diagnostic.Id.t
; message : unit Pp.t
; loc : Loc.t option
; severity : Diagnostic.severity option
; promotion : Diagnostic.Promotion.t list
; directory : string option
; related : Related.t list
}

let sexp_severity =
let open Conv in
enum [ "error", Diagnostic.Error; "warning", Warning ]
;;

let sexp =
let open Conv in
let from { targets; message; loc; severity; promotion; directory; id; related } =
targets, message, loc, severity, promotion, directory, id, related
in
let to_ (targets, message, loc, severity, promotion, directory, id, related) =
{ targets; message; loc; severity; promotion; directory; id; related }
in
let loc = field "loc" (optional Loc.sexp) in
let message = field "message" (required sexp_pp_unit) in
let targets = field "targets" (required (list Target.sexp)) in
let severity = field "severity" (optional sexp_severity) in
let directory = field "directory" (optional string) in
let promotion = field "promotion" (required (list Diagnostic.Promotion.sexp)) in
let id = field "id" (required Diagnostic.Id.sexp) in
let related = field "related" (required (list Related.sexp)) in
iso
(record (eight targets message loc severity promotion directory id related))
to_
from
;;

let to_diagnostic t : Diagnostic.t =
{ targets = t.targets
; message = t.message |> Pp.map_tags ~f:(fun _ -> User_message.Style.Details)
; loc = t.loc
; severity = t.severity
; promotion = t.promotion
; directory = t.directory
; id = t.id
; related = t.related |> List.map ~f:Related.to_diagnostic_related
}
;;

let of_diagnostic (t : Diagnostic.t) =
{ targets = t.targets
; message = t.message |> Pp.map_tags ~f:(fun _ -> ())
; loc = t.loc
; severity = t.severity
; promotion = t.promotion
; directory = t.directory
; id = t.id
; related = t.related |> List.map ~f:Related.of_diagnostic_related
}
;;

module Event = struct
type nonrec t =
| Add of t
| Remove of t

let sexp =
let diagnostic = sexp in
let open Conv in
let add = constr "Add" diagnostic (fun a -> Add a) in
let remove = constr "Remove" diagnostic (fun a -> Remove a) in
sum
[ econstr add; econstr remove ]
(function
| Add t -> case t add
| Remove t -> case t remove)
;;

let to_event : t -> Diagnostic.Event.t = function
| Add t -> Add (to_diagnostic t)
| Remove t -> Remove (to_diagnostic t)
;;

let of_event : Diagnostic.Event.t -> t = function
| Add t -> Add (of_diagnostic t)
| Remove t -> Remove (of_diagnostic t)
;;
end
22 changes: 22 additions & 0 deletions otherlibs/dune-rpc/private/diagnostics_v1.mli
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
(** V1 of the diagnostics module. *)

module Related : sig
type t

val to_diagnostic_related : t -> Exported_types.Diagnostic.Related.t
val of_diagnostic_related : Exported_types.Diagnostic.Related.t -> t
end

type t

val sexp : (t, Conv.values) Conv.t
val to_diagnostic : t -> Exported_types.Diagnostic.t
val of_diagnostic : Exported_types.Diagnostic.t -> t

module Event : sig
type t

val sexp : (t, Conv.values) Conv.t
val to_event : t -> Exported_types.Diagnostic.Event.t
val of_event : Exported_types.Diagnostic.Event.t -> t
end
Loading