@acransac/terminal 中文文档教程

发布于 4年前 浏览 14 项目主页 更新于 3年前

Introduction

terminal 提供了制作终端用户界面的模型。 用户看到一个显示,它是一个atom 或一个显示列表。 一个原子是一个可能带有文本标记的边框框。 使用 streamer,显示器可以对用户或环境生成的事件做出反应。

terminal 受益于 blessed 引入的树状终端图形的高级建模。 它还借鉴了 Lisp 编程语言家族的工具和术语。

How To Use Terminal

终端添加到项目中:

    $ npm install @acransac/terminal

并导入所需的功能:

    const { atom, column, compose, cons, emptyList, indent, inline, label, renderer, row, show, sizeHeight, sizeWidth, TerminalTest, vindent } = require('@acransac/terminal');

Make An Inert Atomic Display

渲染引擎​​使用renderer 进行初始化。 后者返回函数以呈现显示并终止引擎。 原子显示是使用 atom 创建的,并传递给渲染函数。 然后,引擎终止。 一个原子的盒子可以用 label 来标记:

  • renderer:: Maybe -> (显示->(),()->())

    Parameter / Returned Type Description
    output Maybe\ A writable Node.js stream to which the displayed characters and escape sequences are written. Default: process.stdout
    returned (Display -> (), () -> ()) An array of two functions. The first renders on the output the display passed as argument. The second tears down the rendering system

  • atom:: 字符串 -> 显示

    Parameter Type Description
    content String The text to print within the atom box

  • label:: (Atom, String) -> Atom

    Parameter Type Description
    atom Atom\ The atom to label
    title String The label's text
    Examples:

    1.

        const { atom, renderer } = require('@acransac/terminal');
    
        const [render, terminate] = renderer();
    
        render(atom("abc"));
    
        setTimeout(terminate, 2000);
    
        $ node example.js
    

    Alt text

    2.

        const { atom, label, renderer } = require('@acransac/terminal');
    
        const [render, terminate] = renderer();
    
        render(label(atom("abc"), "example"));
    
        setTimeout(terminate, 2000);
    
        $ node example.js
    

    Alt text

    Make An Inert List Display

    如前所述,终端 的工具继承了 Lisp 方言的基本概念。 显示是一种递归结构,表示为显示的嵌套列表。 它是通过cons'ing 显示到列表中构建的,以emptyList 结束这种分支链。 后者可以使用 rowcolumn 来确定高度或宽度的尺寸:

    • 缺点:: (Display, List) -> 列表<显示>

      Parameter Type Description
      display Display The display, atom or list, to prepend
      list List\ The list of displays to prepend to

    • <代码>emptyList:: () -> 列表<显示>

      Returned Type Description
      returned List\ A list display printing nothing. The starting point to which useful displays are prepended

    • <代码>行::数字-> 列表<显示>

      Parameter Type Description
      height Number The empty list's height proportionally to the underlying list's height if any. Otherwise, it is proportional to the screen's height. Expressed in percentage

    • <代码>列::编号-> List

      Parameter Type Description
      width Number The empty list's width proportionally to the underlying list's width if any. Otherwise, it is proportional to the screen's width. Expressed in percentage
      Examples:

      1.

          const { atom, cons, emptyList, renderer } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), emptyList()));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      Alt text

      注意:最后一个示例显示看起来与第一个相同,只是它是一个列表而不是一个原子。

      2.

          const { atom, cons, renderer, row } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), row(50)));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      替换文字

      3.

          const { atom, column, cons, renderer } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), column(50)));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      替换文字

      Size And Position Displays

      sizeWidthsizeHeight 用于调整原子的大小。 indentvindent 位置显示。 它们允许显示具有多个原子或列表可见的列表。 此外,inline 将原子列表放在一行中:

      • <代码>sizeWidth:: (Number, Atom) -> 原子<显示>

        Parameter Type Description
        size Number The atom's width proportionally to the underlying list's width if any. Otherwise, it is proportional to the screen's width. Expressed in percentage
        atom Atom\ The atom to resize

      • <代码>sizeHeight:: (Number, Atom) -> 原子<显示>

        Parameter Type Description
        size Number The atom's height proportionally to the underlying list's height if any. Otherwise, it is proportional to the screen's height. Expressed in percentage
        atom Atom\ The atom to resize

      • 缩进:: (数字, 显示) -> 显示

        Parameter Type Description
        offset Number The display's offset from the underlying list's left edge if any. Otherwise, it is from the screen's left edge. Expressed in percentage of the underlier's width
        display Display The display to move

      • vindent:: (Number, Display) -> 显示

        Parameter Type Description
        offset Number The display's offset from the underlying list's top edge if any. Otherwise, it is from the screen's top edge. Expressed in percentage of the underlier's height
        display Display The display to move

      • inline::List>; -> 显示

        Parameter Type Description
        lat List\> A display that is a list of atoms with specified widths that are to be indented so that they show in a row
        Examples:

        1.

            const { atom, indent, renderer, sizeHeight, sizeWidth, vindent } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(vindent(25, indent(25, sizeHeight(50, sizeWidth(50, atom("abc"))))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        2.

            const { atom, cons, emptyList, indent, renderer, vindent } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(vindent(10, indent(10, cons(atom("abc"), emptyList()))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        3.

            const { atom, cons, emptyList, indent, renderer, sizeWidth } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(cons(sizeWidth(50, atom("abc")),
                        cons(indent(50, sizeWidth(50, atom("def"))),
                             emptyList())));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        替换文字

        4.

            const { atom, cons, emptyList, inline, renderer, sizeWidth } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(inline(cons(sizeWidth(50, atom("abc")),
                               cons(sizeWidth(50, atom("def")),
                                    emptyList()))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        替换文字

        Make A Reactive Display

        例如,当用户与应用程序交互或接收到网络消息时,反应式显示会发生变化。 terminal 使用 streamer 框架来监听事件,并且将响应式显示集成到附加到来源。 此集成由 compose 承担,它将流分发到一系列 组件 并将它们的输出注入到 模板 中。 compose 立即与通过将渲染函数传递给 show 生成的函数链接起来,并执行注入模板的渲染:

        • <代码>组件::任何... -> 任何-> 流 -> 作曲家句柄

          Parameter / Returned Type Description
          parameters Any… The state of the component
          predecessor Any The output of the component on the last event processed
          returned Stream -> ComposerHandle The logic of the component which processes the stream and returns to compose a handle to the parameters and output of the form f => f(updatedParameters)(output). Using this handle, compose provides the parameters and predecessor to the component on the next event, and injects the ouput into the template

        • <代码>模板::组件... -> 显示

          Parameter Type Description
          components Component… A series of components whose output values are passed as arguments to the template

        • compose:: (Template, Component...) -> 作曲家

          Parameter Type Description
          template Template The template organizing the display
          reactiveComponents Component… A sequence of components parameterizing the template

        • show::显示-> () -> 作曲家-> Process

          Parameter Type Description
          render Display -> () The render function returned by renderer
          Example:
              const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
              const { atom, compose, renderer, show } = require('@acransac/terminal');
          
              const [render, terminate] = renderer();
          
              const loop = async (stream) => {
                if (value(now(stream)) === "end") {
                  return terminate();
                }
                else {
                  return loop(await continuation(now(stream))(forget(await later(stream))));
                }
              };
          
              const template = component => atom(component);
          
              const component = noParameters => predecessor => stream => {
                const processed = predecessor ? predecessor : "";
          
                if (value(now(stream)) === "end") {
                  return f => f(noParameters)(processed);
                }
                else {
                  return f => f(noParameters)(`${processed}${value(now(stream))}`);
                }
              };
          
              Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                    .withDownstream(async (stream) => loop(await show(render)(compose(template, component))(stream)));
          
              $ node example.js
          

          Alt text

          Test The Display

          TerminalTest.reviewDisplays 引入了对一系列显示的测试。 使用 makeTestableInertDisplaymakeTestableReactiveDisplay 创建显示测试。 运行时,执行此检查的脚本接受一个命令行选项:look 依次显示显示,以便可以直观地检查它们。 save 将显示的字符和转义序列写入文件,以便可以通过编程方式验证它们。 control 运行实际测试,将生成的显示与控制文件进行比较并记录成功和失败。 这是默认选项:

          • TerminalTest.reviewDisplays:: ([TestableDisplay], Maybe) -> ()

            Parameter Type Description
            testableDisplays [TestableDisplay] An array of testable displays, whether inert or reactive
            testSuiteName Maybe\ The name of the test suite that appears in logs. Default: Test Suite

          • TerminalTest.makeTestableInertDisplay:: (() -> Display, String) -> 可测试显示

            Parameter Type Description
            display () -> Display A deferred inert display
            testName String The name of the test that appears in logs

          • TerminalTest.makeTestableReactiveDisplay:: (ReactiveDisplayTest, String, Maybe) -> 可测试显示

            Parameter Type Description
            produceDisplay ReactiveDisplayTest The test function displaying what is to be checked. Its signature depends on the setup done by the initializer. By default, it should provide a placeholder for the render function as first argument, and then a placeholder for the continuation of the test suite. The test runner provides the actual functions when executing
            testName String The name of the test that appears in logs
            init Maybe\ Logic to execute before running the test. Default: calls renderer

          • <代码>TestInitializer:: (Stream.Writable, ReactiveDisplayTest, () -> ()) -> ()

            Parameter Type Description
            displayTarget Stream.Writable A reference to the target for writing the characters and escape sequences of the display. It could be a file or the standard output depending on the mode of the test runner
            test ReactiveDisplayTest A reference to the test function to call once the initialization is done
            finish () -> () A reference to the continuation of the test to call once the test is done
            Examples:

            1.

                const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
                const { atom, compose, show, TerminalTest } = require('@acransac/terminal');
            
                function reactiveDisplayTest(render, finish) {
                  const loop = async (stream) => {
                    if (value(now(stream)) === "end") {
                      return finish();
                    }
                    else {
                      return loop(await continuation(now(stream))(forget(await later(stream))));
                    }
                  };
            
                  const template = component => atom(component);
            
                  const component = noParameters => predecessor => stream => {
                    const processed = predecessor ? predecessor : "";
            
                    if (value(now(stream)) === "end") {
                      return f => f(noParameters)(processed);
                    }
                    else {
                      return f => f(noParameters)(`${processed}${value(now(stream))}`);
                    }
                  };
            
                  Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                        .withDownstream(async (stream) => loop(await show(render)(compose(template, component))(stream)));
                }
            
                TerminalTest.reviewDisplays([
                  TerminalTest.makeTestableInertDisplay(() => atom("abc"), "Inert Display"),
                  TerminalTest.makeTestableReactiveDisplay(reactiveDisplayTest, "Reactive Display")
                ], "Example Tests");
            
                $ node example.js look
            

            替代文字

                $ node example.js save
                $ node example.js control
                --------------------
                Example Tests:
            
                    2 / 2 test(s) passed
                --------------------
            

            2.

                const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
                const { atom, compose, renderer, show, TerminalTest } = require('@acransac/terminal');
            
                function reactiveDisplayTest(render, finish) {
                  const loop = async (stream) => {
                    if (value(now(stream)) === "end") {
                      return finish();
                    }
                    else {
                      return loop(await continuation(now(stream))(forget(await later(stream))));
                    }
                  };
            
                  const template = component => atom(component);
            
                  const component = noParameters => predecessor => stream => {
                    const processed = predecessor ? predecessor : "";
            
                    if (value(now(stream)) === "end") {
                      return f => f(noParameters)(processed);
                    }
                    else {
                      return f => f(noParameters)(`${processed}${value(now(stream))}`);
                    }
                  };
            
                  return async (stream) => loop(await show(render)(compose(template, component))(stream));
                }
            
                function testInitializer(displayTarget, test, finish) {
                  const [render, terminate] = renderer(displayTarget);
            
                  const conclude = () => {
                    terminate();
            
                    return finish();
                  }
            
                  Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                                          .withDownstream(async (stream) => test(render, conclude)(stream));
                }
            
                TerminalTest.reviewDisplays([
                  TerminalTest.makeTestableReactiveDisplay(reactiveDisplayTest,
                                                           "Reactive Display With Initializer",
                                                           testInitializer)
                ], "Example Tests");
            
                $ node example.js look
            

            替代文字

                $ node example.js save
                $ node example.js control
                --------------------
                Example Tests:
            
                    1 / 1 test(s) passed
                --------------------
            

Introduction

terminal provides a model to make terminal user interfaces. The user sees a display which is either an atom or a list of displays. An atom is a possibly labelled bordered box with text. Using streamer, a display can react to events generated by the user or the environment.

terminal benefits from the high-level modelling of terminal graphics as a tree introduced by blessed. It also borrows its tools and terminology from the Lisp family of programming languages.

How To Use Terminal

Add terminal to a project with:

    $ npm install @acransac/terminal

and import the needed functionalities:

    const { atom, column, compose, cons, emptyList, indent, inline, label, renderer, row, show, sizeHeight, sizeWidth, TerminalTest, vindent } = require('@acransac/terminal');

Make An Inert Atomic Display

The rendering engine is initialized with renderer. The latter returns functions to render a display and terminate the engine. An atomic display is created with atom and passed to the render function. Then, the engine is terminated. An atom's box can be labelled with label:

  • renderer:: Maybe<Stream.Writable> -> (Display -> (), () -> ())

    Parameter / Returned Type Description
    output Maybe\ A writable Node.js stream to which the displayed characters and escape sequences are written. Default: process.stdout
    returned (Display -> (), () -> ()) An array of two functions. The first renders on the output the display passed as argument. The second tears down the rendering system

  • atom:: String -> Display

    Parameter Type Description
    content String The text to print within the atom box

  • label:: (Atom<Display>, String) -> Atom<Display>

    Parameter Type Description
    atom Atom\ The atom to label
    title String The label's text
    Examples:

    1.

        const { atom, renderer } = require('@acransac/terminal');
    
        const [render, terminate] = renderer();
    
        render(atom("abc"));
    
        setTimeout(terminate, 2000);
    
        $ node example.js
    

    Alt text

    2.

        const { atom, label, renderer } = require('@acransac/terminal');
    
        const [render, terminate] = renderer();
    
        render(label(atom("abc"), "example"));
    
        setTimeout(terminate, 2000);
    
        $ node example.js
    

    Alt text

    Make An Inert List Display

    As mentioned before, terminal's tooling inherits the fundamental notions of the Lisp dialects. A display is a recursive structure expressed as nested lists of displays. It is built by cons'ing displays onto lists, ending such ramified chains with the emptyList. The latter can be dimensioned in height or in width with row or column:

    • cons:: (Display, List<Display>) -> List<Display>

      Parameter Type Description
      display Display The display, atom or list, to prepend
      list List\ The list of displays to prepend to

    • emptyList:: () -> List<Display>

      Returned Type Description
      returned List\ A list display printing nothing. The starting point to which useful displays are prepended

    • row:: Number -> List<Display>

      Parameter Type Description
      height Number The empty list's height proportionally to the underlying list's height if any. Otherwise, it is proportional to the screen's height. Expressed in percentage

    • column:: Number -> List<Display>

      Parameter Type Description
      width Number The empty list's width proportionally to the underlying list's width if any. Otherwise, it is proportional to the screen's width. Expressed in percentage
      Examples:

      1.

          const { atom, cons, emptyList, renderer } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), emptyList()));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      Alt text

      Note: The last example display looks the same as the first one, except that it is a list and not an atom.

      2.

          const { atom, cons, renderer, row } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), row(50)));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      Alt text

      3.

          const { atom, column, cons, renderer } = require('@acransac/terminal');
      
          const [render, terminate] = renderer();
      
          render(cons(atom("abc"), column(50)));
      
          setTimeout(terminate, 2000);
      
          $ node example.js
      

      Alt text

      Size And Position Displays

      sizeWidth and sizeHeight are used to size atoms. indent and vindent position displays. They allow to make list displays with several atoms or lists visible. Also, inline places a list of atoms in a row:

      • sizeWidth:: (Number, Atom<Display>) -> Atom<Display>

        Parameter Type Description
        size Number The atom's width proportionally to the underlying list's width if any. Otherwise, it is proportional to the screen's width. Expressed in percentage
        atom Atom\ The atom to resize

      • sizeHeight:: (Number, Atom<Display>) -> Atom<Display>

        Parameter Type Description
        size Number The atom's height proportionally to the underlying list's height if any. Otherwise, it is proportional to the screen's height. Expressed in percentage
        atom Atom\ The atom to resize

      • indent:: (Number, Display) -> Display

        Parameter Type Description
        offset Number The display's offset from the underlying list's left edge if any. Otherwise, it is from the screen's left edge. Expressed in percentage of the underlier's width
        display Display The display to move

      • vindent:: (Number, Display) -> Display

        Parameter Type Description
        offset Number The display's offset from the underlying list's top edge if any. Otherwise, it is from the screen's top edge. Expressed in percentage of the underlier's height
        display Display The display to move

      • inline:: List<Atom<Display>> -> Display

        Parameter Type Description
        lat List\> A display that is a list of atoms with specified widths that are to be indented so that they show in a row
        Examples:

        1.

            const { atom, indent, renderer, sizeHeight, sizeWidth, vindent } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(vindent(25, indent(25, sizeHeight(50, sizeWidth(50, atom("abc"))))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        2.

            const { atom, cons, emptyList, indent, renderer, vindent } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(vindent(10, indent(10, cons(atom("abc"), emptyList()))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        3.

            const { atom, cons, emptyList, indent, renderer, sizeWidth } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(cons(sizeWidth(50, atom("abc")),
                        cons(indent(50, sizeWidth(50, atom("def"))),
                             emptyList())));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        4.

            const { atom, cons, emptyList, inline, renderer, sizeWidth } = require('@acransac/terminal');
        
            const [render, terminate] = renderer();
        
            render(inline(cons(sizeWidth(50, atom("abc")),
                               cons(sizeWidth(50, atom("def")),
                                    emptyList()))));
        
            setTimeout(terminate, 2000);
        
            $ node example.js
        

        Alt text

        Make A Reactive Display

        A reactive display changes as the user interacts with the application or network messages are received, for example. terminal uses the streamer framework to listen to events and a reactive display is integrated into the process attached to the source. This integration is borne by compose which distributes the stream to a series of components and injects their output into a template. compose is immediately chained with the function generated by passing the render function to show and that executes the rendering of the injected template:

        • Component:: Any... -> Any -> Stream -> ComposerHandle

          Parameter / Returned Type Description
          parameters Any… The state of the component
          predecessor Any The output of the component on the last event processed
          returned Stream -> ComposerHandle The logic of the component which processes the stream and returns to compose a handle to the parameters and output of the form f => f(updatedParameters)(output). Using this handle, compose provides the parameters and predecessor to the component on the next event, and injects the ouput into the template

        • Template:: Component... -> Display

          Parameter Type Description
          components Component… A series of components whose output values are passed as arguments to the template

        • compose:: (Template, Component...) -> Composer

          Parameter Type Description
          template Template The template organizing the display
          reactiveComponents Component… A sequence of components parameterizing the template

        • show:: Display -> () -> Composer -> Process

          Parameter Type Description
          render Display -> () The render function returned by renderer
          Example:
              const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
              const { atom, compose, renderer, show } = require('@acransac/terminal');
          
              const [render, terminate] = renderer();
          
              const loop = async (stream) => {
                if (value(now(stream)) === "end") {
                  return terminate();
                }
                else {
                  return loop(await continuation(now(stream))(forget(await later(stream))));
                }
              };
          
              const template = component => atom(component);
          
              const component = noParameters => predecessor => stream => {
                const processed = predecessor ? predecessor : "";
          
                if (value(now(stream)) === "end") {
                  return f => f(noParameters)(processed);
                }
                else {
                  return f => f(noParameters)(`${processed}${value(now(stream))}`);
                }
              };
          
              Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                    .withDownstream(async (stream) => loop(await show(render)(compose(template, component))(stream)));
          
              $ node example.js
          

          Alt text

          Test The Display

          TerminalTest.reviewDisplays introduces testing a sequence of displays. A display test is created with makeTestableInertDisplay or makeTestableReactiveDisplay. When run, a script executing this review accepts one command line option: look shows the displays in turn so that they can be visually checked. save writes the characters and escape sequences of the displays to files so that they can be programmatically verified. control runs the actual test, comparing the generated displays to the control files and logging the successes and failures. It is the default option:

          • TerminalTest.reviewDisplays:: ([TestableDisplay], Maybe<String>) -> ()

            Parameter Type Description
            testableDisplays [TestableDisplay] An array of testable displays, whether inert or reactive
            testSuiteName Maybe\ The name of the test suite that appears in logs. Default: Test Suite

          • TerminalTest.makeTestableInertDisplay:: (() -> Display, String) -> TestableDisplay

            Parameter Type Description
            display () -> Display A deferred inert display
            testName String The name of the test that appears in logs

          • TerminalTest.makeTestableReactiveDisplay:: (ReactiveDisplayTest, String, Maybe<TestInitializer>) -> TestableDisplay

            Parameter Type Description
            produceDisplay ReactiveDisplayTest The test function displaying what is to be checked. Its signature depends on the setup done by the initializer. By default, it should provide a placeholder for the render function as first argument, and then a placeholder for the continuation of the test suite. The test runner provides the actual functions when executing
            testName String The name of the test that appears in logs
            init Maybe\ Logic to execute before running the test. Default: calls renderer

          • TestInitializer:: (Stream.Writable, ReactiveDisplayTest, () -> ()) -> ()

            Parameter Type Description
            displayTarget Stream.Writable A reference to the target for writing the characters and escape sequences of the display. It could be a file or the standard output depending on the mode of the test runner
            test ReactiveDisplayTest A reference to the test function to call once the initialization is done
            finish () -> () A reference to the continuation of the test to call once the test is done
            Examples:

            1.

                const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
                const { atom, compose, show, TerminalTest } = require('@acransac/terminal');
            
                function reactiveDisplayTest(render, finish) {
                  const loop = async (stream) => {
                    if (value(now(stream)) === "end") {
                      return finish();
                    }
                    else {
                      return loop(await continuation(now(stream))(forget(await later(stream))));
                    }
                  };
            
                  const template = component => atom(component);
            
                  const component = noParameters => predecessor => stream => {
                    const processed = predecessor ? predecessor : "";
            
                    if (value(now(stream)) === "end") {
                      return f => f(noParameters)(processed);
                    }
                    else {
                      return f => f(noParameters)(`${processed}${value(now(stream))}`);
                    }
                  };
            
                  Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                        .withDownstream(async (stream) => loop(await show(render)(compose(template, component))(stream)));
                }
            
                TerminalTest.reviewDisplays([
                  TerminalTest.makeTestableInertDisplay(() => atom("abc"), "Inert Display"),
                  TerminalTest.makeTestableReactiveDisplay(reactiveDisplayTest, "Reactive Display")
                ], "Example Tests");
            
                $ node example.js look
            

            Alt text

                $ node example.js save
                $ node example.js control
                --------------------
                Example Tests:
            
                    2 / 2 test(s) passed
                --------------------
            

            2.

                const { continuation, forget, later, now, Source, StreamerTest, value } = require('@acransac/streamer');
                const { atom, compose, renderer, show, TerminalTest } = require('@acransac/terminal');
            
                function reactiveDisplayTest(render, finish) {
                  const loop = async (stream) => {
                    if (value(now(stream)) === "end") {
                      return finish();
                    }
                    else {
                      return loop(await continuation(now(stream))(forget(await later(stream))));
                    }
                  };
            
                  const template = component => atom(component);
            
                  const component = noParameters => predecessor => stream => {
                    const processed = predecessor ? predecessor : "";
            
                    if (value(now(stream)) === "end") {
                      return f => f(noParameters)(processed);
                    }
                    else {
                      return f => f(noParameters)(`${processed}${value(now(stream))}`);
                    }
                  };
            
                  return async (stream) => loop(await show(render)(compose(template, component))(stream));
                }
            
                function testInitializer(displayTarget, test, finish) {
                  const [render, terminate] = renderer(displayTarget);
            
                  const conclude = () => {
                    terminate();
            
                    return finish();
                  }
            
                  Source.from(StreamerTest.emitSequence(["a", "b", "c", "end"], 1000), "onevent")
                                          .withDownstream(async (stream) => test(render, conclude)(stream));
                }
            
                TerminalTest.reviewDisplays([
                  TerminalTest.makeTestableReactiveDisplay(reactiveDisplayTest,
                                                           "Reactive Display With Initializer",
                                                           testInitializer)
                ], "Example Tests");
            
                $ node example.js look
            

            Alt text

                $ node example.js save
                $ node example.js control
                --------------------
                Example Tests:
            
                    1 / 1 test(s) passed
                --------------------
            
更多

友情链接

    我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
    原文