From c56ee8634c7a94fda144f54570bc425e602cb302 Mon Sep 17 00:00:00 2001 From: Ting-Gian LUA Date: Thu, 7 Nov 2024 16:05:30 +0800 Subject: [PATCH] [ doc ] Update CHANGELOG for PR by @vic0103520 --- CHANGELOG.md | 1 + lib/js/src/Config.bs.js | 4 +- lib/js/src/Main.bs.js | 249 ++++++++++++--------------- lib/js/src/State/State__View.bs.js | 2 +- lib/js/src/View/Panel/Panel.bs.js | 27 ++- lib/js/src/View/View.bs.js | 191 ++++++++------------ src/Config.res | 18 +- src/Connection/Connection__Probe.res | 1 - src/Main.res | 27 +-- src/State/State__View.res | 7 +- src/View/Panel/Panel.res | 4 +- src/View/View.res | 79 ++++----- 12 files changed, 265 insertions(+), 345 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41115cd6..2fcc04e5 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ### Fixed - #195: Remove all usage of deprecated api @bs.send.pipe by [@jiangsy](https://github.com/jiangsy) - #191: Add more detailed splitting command description by [@ChAoSUnItY](https://github.com/ChAoSUnItY) +- #169: Custom Agda buffer font size in the extension's setting by [@vic0103520](https://github.com/vic0103520) ### Changed - Upgrade ReScript to v11 diff --git a/lib/js/src/Config.bs.js b/lib/js/src/Config.bs.js index 1d46748b..1fc5d7f5 100644 --- a/lib/js/src/Config.bs.js +++ b/lib/js/src/Config.bs.js @@ -219,7 +219,7 @@ var InputMethod = { getActivationKey: getActivationKey }; -function getFontSize(param) { +function getFontSize() { var config = Vscode.workspace.getConfiguration("agdaMode", undefined); var m = config.get("buffer.fontSize"); var size; @@ -230,7 +230,7 @@ function getFontSize(param) { size = n !== undefined ? Caml_option.valFromOption(n) : 14; } config.update("buffer.fontSize", size, 1, undefined); - return String(size); + return size.toString(); } var $$Buffer = { diff --git a/lib/js/src/Main.bs.js b/lib/js/src/Main.bs.js index f60a35d2..8771d131 100644 --- a/lib/js/src/Main.bs.js +++ b/lib/js/src/Main.bs.js @@ -3,6 +3,7 @@ var Vscode = require("vscode"); var Caml_option = require("rescript/lib/js/caml_option.js"); +var Core__Array = require("@rescript/core/lib/js/src/Core__Array.bs.js"); var Core__Option = require("@rescript/core/lib/js/src/Core__Option.bs.js"); var Caml_splice_call = require("rescript/lib/js/caml_splice_call.js"); var IM$AgdaModeVscode = require("./InputMethod/IM.bs.js"); @@ -63,15 +64,14 @@ var Inputs = { function initialize(channels, extensionPath, globalStoragePath, editor, fileName) { var panel = Singleton$AgdaModeVscode.Panel.make(extensionPath); - $$Promise.get(WebviewPanel$AgdaModeVscode.onceDestroyed(panel), (function (param) { - Registry$AgdaModeVscode.removeAndDestroyAll(undefined); - - })); - var state = State$AgdaModeVscode.make(debugChan, globalStoragePath, extensionPath, editor); - State__View$AgdaModeVscode.Panel.setFontSize(state, Config$AgdaModeVscode.$$Buffer.getFontSize(undefined)); - $$Promise.get(Chan$AgdaModeVscode.once(state.onRemoveFromRegistry), (function (param) { - return Registry$AgdaModeVscode.remove(fileName); - })); + WebviewPanel$AgdaModeVscode.onceDestroyed(panel).finally(function () { + Registry$AgdaModeVscode.removeAndDestroyAll(); + }); + var state = State$AgdaModeVscode.make(channels, globalStoragePath, extensionPath, editor); + State__View$AgdaModeVscode.Panel.setFontSize(state, Config$AgdaModeVscode.$$Buffer.getFontSize()); + Chan$AgdaModeVscode.once(state.onRemoveFromRegistry).finally(function () { + Registry$AgdaModeVscode.remove(fileName); + }); var subscribe = function (disposable) { state.subscriptions.push(disposable); }; @@ -180,134 +180,111 @@ function activateWithoutContext(subscriptions, extensionPath, globalStoragePath) commandHandled: channels_commandHandled, log: channels_log }; - - var x = onOpenEditor(function (editor) { - var fileName = Parser$AgdaModeVscode.filepath(editor.document.fileName); - if (isAgda(fileName)) { - return Belt_Option.forEach(Registry$AgdaModeVscode.get(fileName), (function (state) { - state.editor = editor; - state.document = editor.document; - State__Command$AgdaModeVscode.dispatchCommand(state, /* Refresh */3); - - })); - } - - }); - subscriptions.push(x); - var x$1 = Vscode.workspace.onDidChangeTextDocument(function ($$event) { - var $$document = $$event.document; - var fileName = Parser$AgdaModeVscode.filepath($$document.fileName); - if (isAgda(fileName)) { - return Belt_Option.forEach(Registry$AgdaModeVscode.get(fileName), (function (state) { - return Highlighting$AgdaModeVscode.updateSemanticHighlighting(state.highlighting, $$event); - })); - } - - }); - subscriptions.push(x$1); - var x$2 = Vscode.workspace.onDidChangeConfiguration(function ($$event) { - var state = Belt_Array.reduce(Vscode.window.visibleTextEditors, undefined, (function (state, editor) { - if (state !== undefined) { - return state; - } else { - return Registry$AgdaModeVscode.get(Parser$AgdaModeVscode.filepath(editor.document.fileName)); - } - })); - var fontSizeChanged = $$event.affectsConfiguration("agdaMode.buffer.fontSize", undefined); - if (!fontSizeChanged) { - return ; - } - var size = Config$AgdaModeVscode.$$Buffer.getFontSize(undefined); - if (state !== undefined) { - State__View$AgdaModeVscode.Panel.setFontSize(state, size); - return ; - } - - }); - subscriptions.push(x$2); - var x$3 = Vscode.workspace.onDidCloseTextDocument(function ($$document) { - var fileName = Parser$AgdaModeVscode.filepath($$document.fileName); - if (isAgda(fileName)) { - Registry$AgdaModeVscode.removeAndDestroy(fileName); - finalize(false); - return ; - } - - }); - subscriptions.push(x$3); - var xs = onTriggerCommand(function (command, editor) { - var fileName = Parser$AgdaModeVscode.filepath(editor.document.fileName); - var tmp; - if (typeof command === "number" && command < 3) { - switch (command) { - case /* Load */0 : - tmp = $$Promise.resolved(undefined); - break; - case /* Quit */1 : - tmp = $$Promise.flatMap(Registry$AgdaModeVscode.removeAndDestroy(fileName), (function (param) { - return finalize(false); - })); - break; - case /* Restart */2 : - tmp = $$Promise.flatMap(Registry$AgdaModeVscode.removeAndDestroy(fileName), (function (param) { - return finalize(true); - })); - break; + subscribe(onOpenEditor(function (editor) { + var fileName = Parser$AgdaModeVscode.filepath(editor.document.fileName); + if (isAgda(fileName)) { + return Core__Option.forEach(Registry$AgdaModeVscode.get(fileName), (function (state) { + state.editor = editor; + state.document = editor.document; + State__Command$AgdaModeVscode.dispatchCommand(state, "Refresh"); + })); + } - } - } else { - tmp = $$Promise.resolved(undefined); - } - return $$Promise.flatMap($$Promise.tap(tmp, (function (param) { - if (typeof command === "number") { - switch (command) { - case /* Load */0 : - case /* Restart */2 : - break; - default: - return ; - } - } else { - if (command.TAG !== /* InputMethod */14) { - return ; - } - if (command._0 !== 0) { - return ; - } - - } - var match = Registry$AgdaModeVscode.get(fileName); - if (match !== undefined) { - return ; - } - var state = initialize(channels, extensionPath, globalStoragePath, editor, fileName); - return Registry$AgdaModeVscode.add(fileName, state); - })), (function (param) { - var state = Registry$AgdaModeVscode.get(fileName); - if (state !== undefined) { - return $$Promise.map(State__Command$AgdaModeVscode.dispatchCommand(state, command), (function (result) { - if (result.TAG === /* Ok */0) { - return { - TAG: 0, - _0: state, - [Symbol.for("name")]: "Ok" - }; - } else { - return { - TAG: 1, - _0: result._0, - [Symbol.for("name")]: "Error" - }; - } - })); - } else { - return $$Promise.resolved(undefined); - } - })); - }); - Caml_splice_call.spliceObjApply(subscriptions, "push", [xs]); - var x$4 = registerDocumentSemanticTokensProvider(undefined); - subscriptions.push(x$4); + })); + subscribe(Vscode.workspace.onDidChangeTextDocument(function ($$event) { + var $$document = $$event.document; + var fileName = Parser$AgdaModeVscode.filepath($$document.fileName); + if (isAgda(fileName)) { + return Core__Option.forEach(Registry$AgdaModeVscode.get(fileName), (function (state) { + Highlighting$AgdaModeVscode.updateSemanticHighlighting(state.highlighting, $$event); + })); + } + + })); + subscribe(Vscode.workspace.onDidChangeConfiguration(function ($$event) { + var getFileName = function (editor) { + return Parser$AgdaModeVscode.filepath(editor.document.fileName); + }; + var state = Core__Array.reduce(Vscode.window.visibleTextEditors, undefined, (function (state, editor) { + if (state !== undefined) { + return state; + } else { + return Registry$AgdaModeVscode.get(getFileName(editor)); + } + })); + var fontSizeChanged = $$event.affectsConfiguration("agdaMode.buffer.fontSize", undefined); + if (!fontSizeChanged) { + return ; + } + var size = Config$AgdaModeVscode.$$Buffer.getFontSize(); + if (state !== undefined) { + State__View$AgdaModeVscode.Panel.setFontSize(state, size); + return ; + } + + })); + subscribe(Vscode.workspace.onDidCloseTextDocument(function ($$document) { + var fileName = Parser$AgdaModeVscode.filepath($$document.fileName); + if (isAgda(fileName)) { + Registry$AgdaModeVscode.removeAndDestroy(fileName); + finalize(false); + return ; + } + + })); + subscribeMany(onTriggerCommand(async function (command, editor) { + var fileName = Parser$AgdaModeVscode.filepath(editor.document.fileName); + if (typeof command !== "object") { + switch (command) { + case "Quit" : + await Registry$AgdaModeVscode.removeAndDestroy(fileName); + finalize(false); + break; + case "Restart" : + await Registry$AgdaModeVscode.removeAndDestroy(fileName); + finalize(true); + break; + default: + + } + } + var exit = 0; + if (typeof command !== "object") { + switch (command) { + case "Load" : + case "Restart" : + exit = 1; + break; + default: + + } + } else if (command.TAG === "InputMethod") { + var tmp = command._0; + if (typeof tmp !== "object" && tmp === "Activate") { + exit = 1; + } + + } + if (exit === 1) { + var match = Registry$AgdaModeVscode.get(fileName); + if (match === undefined) { + var state = initialize(channels, extensionPath, globalStoragePath, editor, fileName); + Registry$AgdaModeVscode.add(fileName, state); + } + + } + var state$1 = Registry$AgdaModeVscode.get(fileName); + if (state$1 !== undefined) { + await State__Command$AgdaModeVscode.dispatchCommand(state$1, command); + return { + TAG: "Ok", + _0: state$1, + [Symbol.for("name")]: "Ok" + }; + } + + })); + subscribe(registerDocumentSemanticTokensProvider()); return channels; } diff --git a/lib/js/src/State/State__View.bs.js b/lib/js/src/State/State__View.bs.js index 52022b86..b6f549bf 100644 --- a/lib/js/src/State/State__View.bs.js +++ b/lib/js/src/State/State__View.bs.js @@ -102,7 +102,7 @@ function updatePromptIM(state, content) { function setFontSize(state, fontSize) { return sendEvent(state, { - TAG: 5, + TAG: "ConfigurationChange", _0: fontSize, [Symbol.for("name")]: "ConfigurationChange" }); diff --git a/lib/js/src/View/Panel/Panel.bs.js b/lib/js/src/View/Panel/Panel.bs.js index 44f9c7e0..d1797e9b 100644 --- a/lib/js/src/View/Panel/Panel.bs.js +++ b/lib/js/src/View/Panel/Panel.bs.js @@ -167,20 +167,19 @@ function Panel(props) { }); case "PromptIMUpdate" : var text$1 = $$event._0; - - return Curry._1(setPrompt, (function (x) { - if (x !== undefined) { - return [ - x[0], - x[1], - text$1 - ]; - } - - })); - case /* InputMethod */4 : - return Curry._1(runInputMethodAction, $$event._0); - case /* ConfigurationChange */5 : + return setPrompt(function (x) { + if (x !== undefined) { + return [ + x[0], + x[1], + text$1 + ]; + } + + }); + case "InputMethod" : + return runInputMethodAction($$event._0); + case "ConfigurationChange" : onSubmit(undefined); return setFontSize($$event._0); diff --git a/lib/js/src/View/View.bs.js b/lib/js/src/View/View.bs.js index d69462d0..67211965 100644 --- a/lib/js/src/View/View.bs.js +++ b/lib/js/src/View/View.bs.js @@ -282,7 +282,7 @@ function toString$1(x) { return "PromptIMUpdate " + x._0; case "InputMethod" : return "InputMethod"; - case /* ConfigurationChange */5 : + case "ConfigurationChange" : return "ConfigurationChange"; } @@ -305,17 +305,15 @@ var decode$3 = Util$AgdaModeVscode.Decode.sum(function (x) { }; case "ConfigurationChange" : return { - TAG: 0, - _0: (function (param) { - return Json_decode.map((function (size) { - return { - TAG: 5, - _0: size, - [Symbol.for("name")]: "ConfigurationChange" - }; - }), Json_decode.string, param); - }), - [Symbol.for("name")]: "Contents" + TAG: "Payload", + _0: Json_Decode$JsonCombinators.map(Json_Decode$JsonCombinators.string, (function (text) { + return { + TAG: "ConfigurationChange", + _0: text, + [Symbol.for("name")]: "ConfigurationChange" + }; + })), + [Symbol.for("name")]: "Payload" }; case "Display" : return { @@ -381,115 +379,66 @@ var decode$3 = Util$AgdaModeVscode.Decode.sum(function (x) { } }); - -function encode$3(x) { - if (typeof x === "number") { - return Json_encode.object_({ - hd: [ - "tag", - "PromptInterrupt" - ], - tl: /* [] */0 - }); - } - switch (x.TAG | 0) { - case /* Display */0 : - return Json_encode.object_({ - hd: [ - "tag", - "Display" - ], - tl: { - hd: [ - "contents", - Json_encode.pair(encode, (function (param) { - return Json_encode.array(Item$AgdaModeVscode.encode, param); - }), [ - x._0, - x._1 - ]) - ], - tl: /* [] */0 - } - }); - case /* Append */1 : - return Json_encode.object_({ - hd: [ - "tag", - "Append" - ], - tl: { - hd: [ - "contents", - Json_encode.pair(encode, (function (param) { - return Json_encode.array(Item$AgdaModeVscode.encode, param); - }), [ - x._0, - x._1 - ]) - ], - tl: /* [] */0 - } - }); - case /* SetStatus */2 : - return Json_encode.object_({ - hd: [ - "tag", - "SetStatus" - ], - tl: { - hd: [ - "contents", - x._0 - ], - tl: /* [] */0 - } - }); - case /* PromptIMUpdate */3 : - return Json_encode.object_({ - hd: [ - "tag", - "PromptIMUpdate" - ], - tl: { - hd: [ - "contents", - x._0 - ], - tl: /* [] */0 - } - }); - case /* InputMethod */4 : - return Json_encode.object_({ - hd: [ - "tag", - "InputMethod" - ], - tl: { - hd: [ - "contents", - encode$2(x._0) - ], - tl: /* [] */0 - } - }); - case /* ConfigurationChange */5 : - return Json_encode.object_({ - hd: [ - "tag", - "ConfigurationChange" - ], - tl: { - hd: [ - "contents", - x._0 - ], - tl: /* [] */0 - } - }); - - } -} +var encode$3 = Util$AgdaModeVscode.Encode.sum(function (x) { + if (typeof x !== "object") { + return { + TAG: "TagOnly", + _0: "PromptInterrupt", + [Symbol.for("name")]: "TagOnly" + }; + } + switch (x.TAG) { + case "Display" : + return { + TAG: "Payload", + _0: "Display", + _1: Json_Encode$JsonCombinators.tuple2(encode, Json_Encode$JsonCombinators.array(Item$AgdaModeVscode.encode))([ + x._0, + x._1 + ]), + [Symbol.for("name")]: "Payload" + }; + case "Append" : + return { + TAG: "Payload", + _0: "Append", + _1: Json_Encode$JsonCombinators.tuple2(encode, Json_Encode$JsonCombinators.array(Item$AgdaModeVscode.encode))([ + x._0, + x._1 + ]), + [Symbol.for("name")]: "Payload" + }; + case "SetStatus" : + return { + TAG: "Payload", + _0: "SetStatus", + _1: x._0, + [Symbol.for("name")]: "Payload" + }; + case "PromptIMUpdate" : + return { + TAG: "Payload", + _0: "PromptIMUpdate", + _1: x._0, + [Symbol.for("name")]: "Payload" + }; + case "InputMethod" : + return { + TAG: "Payload", + _0: "InputMethod", + _1: encode$2(x._0), + [Symbol.for("name")]: "Payload" + }; + case "ConfigurationChange" : + return { + TAG: "Payload", + _0: "ConfigurationChange", + _1: x._0, + [Symbol.for("name")]: "Payload" + }; + + } + }); var EventToView = { InputMethod: InputMethod, diff --git a/src/Config.res b/src/Config.res index c99d767d..0bb1fa88 100644 --- a/src/Config.res +++ b/src/Config.res @@ -208,19 +208,19 @@ module InputMethod = { module Buffer = { let getFontSize = () => { let config = Workspace.getConfiguration(Some("agdaMode"), None) - let size = - switch config->WorkspaceConfiguration.get("buffer.fontSize") { - | Some(m) => m - | None => - switch Workspace.getConfiguration(Some("editor"), None)->WorkspaceConfiguration.get("fontSize") { - | Some(n) => n - | _ => 14 - } + let size = switch config->WorkspaceConfiguration.get("buffer.fontSize") { + | Some(m) => m + | None => + switch Workspace.getConfiguration(Some("editor"), None)->WorkspaceConfiguration.get( + "fontSize", + ) { + | Some(n) => n + | _ => 14 } + } config->WorkspaceConfiguration.updateGlobalSettings("buffer.fontSize", size, None)->ignore size->Int.toString } } - diff --git a/src/Connection/Connection__Probe.res b/src/Connection/Connection__Probe.res index 1576f490..1be8f80d 100644 --- a/src/Connection/Connection__Probe.res +++ b/src/Connection/Connection__Probe.res @@ -1,7 +1,6 @@ module Version = Util.Version open LanguageServerMule open Source.GitHub -open Belt // module Platform = { // module GetOs = { diff --git a/src/Main.res b/src/Main.res index 00f87630..99f371c6 100644 --- a/src/Main.res +++ b/src/Main.res @@ -46,7 +46,7 @@ let initialize = (channels, extensionPath, globalStoragePath, editor, fileName) ->Promise.done // not in the Registry, instantiate a State - let state = State.make(debugChan, globalStoragePath, extensionPath, editor) + let state = State.make(channels, globalStoragePath, extensionPath, editor) // Set panel's font size by configuration state->State__View.Panel.setFontSize(Config.Buffer.getFontSize())->ignore // remove it from the Registry on request @@ -252,22 +252,29 @@ let activateWithoutContext = (subscriptions, extensionPath, globalStoragePath) = } })->subscribe - VSCode.Workspace.onDidChangeConfiguration(.(event: VSCode.ConfigurationChangeEvent.t) => { - let getFileName = editor => editor->VSCode.TextEditor.document->VSCode.TextDocument.fileName->Parser.filepath + VSCode.Workspace.onDidChangeConfiguration((event: VSCode.ConfigurationChangeEvent.t) => { + let getFileName = editor => + editor->VSCode.TextEditor.document->VSCode.TextDocument.fileName->Parser.filepath // Maybe we should check active editor // or define some methods to send events without state since changing style is irrelevant to states of eidtors // (Currently, sending an event to the webview has to get the view from a state and send the event with the view) - let state = Array.reduce(VSCode.Window.visibleTextEditors, None, (state, editor) => { switch state { - | None => editor->getFileName->Registry.get - | _ => state - }}) - let fontSizeChanged = event->VSCode.ConfigurationChangeEvent.affectsConfiguration("agdaMode.buffer.fontSize", #Others(None)) - + let state = Array.reduce(VSCode.Window.visibleTextEditors, None, (state, editor) => { + switch state { + | None => editor->getFileName->Registry.get + | _ => state + } + }) + let fontSizeChanged = + event->VSCode.ConfigurationChangeEvent.affectsConfiguration( + "agdaMode.buffer.fontSize", + #Others(None), + ) + if fontSizeChanged { let size = Config.Buffer.getFontSize() switch state { | Some(state) => state->State__View.Panel.setFontSize(size)->ignore - | None => () + | None => () } } })->subscribe diff --git a/src/State/State__View.res b/src/State/State__View.res index 2de54b8b..8f46de35 100644 --- a/src/State/State__View.res +++ b/src/State/State__View.res @@ -16,12 +16,7 @@ module type Panel = { let updateIM: (state, View.EventToView.InputMethod.t) => Promise.t let updatePromptIM: (state, string) => Promise.t // Prompt - let prompt: ( - state, - View.Header.t, - View.Prompt.t, - string => Promise.t, - ) => Promise.t + let prompt: (state, View.Header.t, View.Prompt.t, string => Promise.t) => Promise.t let interruptPrompt: state => Promise.t // Style let setFontSize: (state, string) => Promise.t diff --git a/src/View/Panel/Panel.res b/src/View/Panel/Panel.res index 15957285..5167605b 100644 --- a/src/View/Panel/Panel.res +++ b/src/View/Panel/Panel.res @@ -26,7 +26,7 @@ let make = ( let (inputMethodState, runInputMethodAction) = React.useReducer(Keyboard.reducer, None) let setFontSize = %raw(` function (n) { document.documentElement.style.setProperty("--agdaMode-buffer-font-size", n + "px"); } `) - + // emit event Initialized on mount React.useEffect1(() => { onEventFromView->Chan.emit(Initialized) @@ -100,7 +100,7 @@ let make = ( setHeader(_ => header) setBody(old => Array.concat(old, body)) // append instead of flush | SetStatus(text) => setStatus(_ => text) - | ConfigurationChange(n) => + | ConfigurationChange(n) => onSubmit(None) setFontSize(n) } diff --git a/src/View/View.res b/src/View/View.res index 940f5cb0..7d4451f6 100644 --- a/src/View/View.res +++ b/src/View/View.res @@ -143,50 +143,43 @@ module EventToView = { | ConfigurationChange(_) => "ConfigurationChange" } + let decode = { + open JsonCombinators.Json.Decode + Util.Decode.sum(x => { + switch x { + | "Display" => + Payload( + tuple2(Header.decode, array(Item.decode))->map(((header, body)) => Display(header, body)), + ) + | "Append" => + Payload( + tuple2(Header.decode, array(Item.decode))->map(((header, body)) => Append(header, body)), + ) + | "SetStatus" => Payload(string->map(text => SetStatus(text))) + | "PromptInterrupt" => TagOnly(PromptInterrupt) + | "PromptIMUpdate" => Payload(string->map(text => PromptIMUpdate(text))) + | "InputMethod" => Payload(InputMethod.decode->map(payload => InputMethod(payload))) + | "ConfigurationChange" => Payload(string->map(text => ConfigurationChange(text))) + | tag => raise(DecodeError("[EventToView] Unknown constructor: " ++ tag)) + } + }) + } - // JSON encode/decode - let decode: Json.Decode.decoder = Util.Decode.sum(x => { - open Json.Decode - switch x { - | "Display" => - Contents( - pair(Header.decode, array(Item.decode)) |> map(((header, body)) => Display(header, body)), - ) - | "Append" => - Contents( - pair(Header.decode, array(Item.decode)) |> map(((header, body)) => Append(header, body)), - ) - | "SetStatus" => Contents(string |> map(text => SetStatus(text))) - | "PromptInterrupt" => TagOnly(PromptInterrupt) - | "PromptIMUpdate" => Contents(string |> map(text => PromptIMUpdate(text))) - | "InputMethod" => Contents(InputMethod.decode |> map(x => InputMethod(x))) - | "ConfigurationChange" => Contents(string |> map(size => ConfigurationChange(size))) - | tag => raise(DecodeError("[EventToView] Unknown constructor: " ++ tag)) - } - }) - - let encode: Json.Encode.encoder = x => { - open Json.Encode - switch x { - | Display(header, body) => - object_(list{ - ("tag", string("Display")), - ("contents", (header, body) |> pair(Header.encode, array(Item.encode))), - }) - - | Append(header, body) => - object_(list{ - ("tag", string("Append")), - ("contents", (header, body) |> pair(Header.encode, array(Item.encode))), - }) - | SetStatus(text) => object_(list{("tag", string("SetStatus")), ("contents", text |> string)}) - | PromptInterrupt => object_(list{("tag", string("PromptInterrupt"))}) - | PromptIMUpdate(text) => - object_(list{("tag", string("PromptIMUpdate")), ("contents", text |> string)}) - | InputMethod(payload) => - object_(list{("tag", string("InputMethod")), ("contents", payload |> InputMethod.encode)}) - | ConfigurationChange(size) => object_(list{("tag", string("ConfigurationChange")), ("contents", size |> string)}) - } + let encode = { + open JsonCombinators.Json.Encode + Util.Encode.sum(x => + switch x { + | Display(header, body) => + Payload("Display", tuple2(Header.encode, array(Item.encode))((header, body))) + | Append(header, body) => + Payload("Append", tuple2(Header.encode, array(Item.encode))((header, body))) + | SetStatus(text) => Payload("SetStatus", string(text)) + | PromptInterrupt => TagOnly("PromptInterrupt") + | PromptIMUpdate(text) => Payload("PromptIMUpdate", string(text)) + | InputMethod(payload) => Payload("InputMethod", InputMethod.encode(payload)) + | ConfigurationChange(text) => Payload("ConfigurationChange", string(text)) + } + , ...) } }