[{"data":1,"prerenderedAt":493},["ShallowReactive",2],{"navigation_docs":3,"-guide-terminal":223,"-guide-terminal-surround":488},[4,26,96,105,202],{"title":5,"icon":6,"path":7,"stem":8,"children":9,"page":25},"Getting started","i-lucide-rocket","\u002Fgetting-started","1.getting-started",[10,15,20],{"title":11,"path":12,"stem":13,"icon":14},"Installation","\u002Fgetting-started\u002Finstallation","1.getting-started\u002F1.installation","i-lucide-download",{"title":16,"path":17,"stem":18,"icon":19},"The first app","\u002Fgetting-started\u002Ffirst-app","1.getting-started\u002F2.first-app","i-lucide-play",{"title":21,"path":22,"stem":23,"icon":24},"The first test","\u002Fgetting-started\u002Ffirst-test","1.getting-started\u002F3.first-test","i-lucide-flask-conical",false,{"title":27,"icon":28,"path":29,"stem":30,"children":31,"page":25},"Guide","i-lucide-book-open","\u002Fguide","2.guide",[32,37,42,47,52,57,62,67,72,77,81,86,91],{"title":33,"path":34,"stem":35,"icon":36},"Components","\u002Fguide\u002Fcomponents","2.guide\u002F01.components","i-lucide-component",{"title":38,"path":39,"stem":40,"icon":41},"Inputs and forms","\u002Fguide\u002Finputs-and-forms","2.guide\u002F02.inputs-and-forms","i-lucide-text-cursor-input",{"title":43,"path":44,"stem":45,"icon":46},"Scrolling and viewports","\u002Fguide\u002Fscrolling","2.guide\u002F03.scrolling","i-lucide-scroll-text",{"title":48,"path":49,"stem":50,"icon":51},"Overlays and layers","\u002Fguide\u002Foverlays","2.guide\u002F04.overlays","i-lucide-layers",{"title":53,"path":54,"stem":55,"icon":56},"Styles and theme","\u002Fguide\u002Fstyles","2.guide\u002F05.styles","i-lucide-palette",{"title":58,"path":59,"stem":60,"icon":61},"Composables","\u002Fguide\u002Fcomposables","2.guide\u002F06.composables","i-lucide-puzzle",{"title":63,"path":64,"stem":65,"icon":66},"Widgets","\u002Fguide\u002Fwidgets","2.guide\u002F07.widgets","i-lucide-blocks",{"title":68,"path":69,"stem":70,"icon":71},"The assistant","\u002Fguide\u002Fassistant","2.guide\u002F08.assistant","i-lucide-message-square",{"title":73,"path":74,"stem":75,"icon":76},"The same app on the web","\u002Fguide\u002Fweb","2.guide\u002F09.web","i-lucide-globe",{"title":78,"path":79,"stem":80,"icon":24},"Testing","\u002Fguide\u002Ftesting","2.guide\u002F10.testing",{"title":82,"path":83,"stem":84,"icon":85},"Running and packaging","\u002Fguide\u002Fpackaging","2.guide\u002F11.packaging","i-lucide-package",{"title":87,"path":88,"stem":89,"icon":90},"The terminal contract","\u002Fguide\u002Fterminal","2.guide\u002F12.terminal","i-lucide-square-terminal",{"title":92,"path":93,"stem":94,"icon":95},"Benchmarks","\u002Fguide\u002Fbenchmarks","2.guide\u002F13.benchmarks","i-lucide-gauge",{"title":97,"icon":98,"path":99,"stem":100,"children":101,"page":25},"AI and agents","i-lucide-bot","\u002Fai","3.ai",[102],{"title":97,"path":103,"stem":104,"icon":98},"\u002Fai\u002Fagents","3.ai\u002F1.agents",{"title":106,"icon":107,"path":108,"stem":109,"children":110},"Decisions","i-lucide-scale","\u002Fdecisions","4.decisions",[111,114,118,122,126,130,134,138,142,146,150,154,158,162,166,170,174,178,182,186,190,194,198],{"title":112,"path":108,"stem":113,"icon":46},"All decisions","4.decisions\u002Findex",{"title":115,"path":116,"stem":117},"0001. kyo-ui is the DSL","\u002Fdecisions\u002F0001-kyo-ui-is-the-dsl","4.decisions\u002F0001-kyo-ui-is-the-dsl",{"title":119,"path":120,"stem":121},"0002. jatatui renders the cells","\u002Fdecisions\u002F0002-jatatui-renders-the-cells","4.decisions\u002F0002-jatatui-renders-the-cells",{"title":123,"path":124,"stem":125},"0003. Pin Kyo 1.0.0-RC7 and JDK 25","\u002Fdecisions\u002F0003-pin-kyo-rc7-and-jdk-25","4.decisions\u002F0003-pin-kyo-rc7-and-jdk-25",{"title":127,"path":128,"stem":129},"0004. Public Kyo APIs only","\u002Fdecisions\u002F0004-public-kyo-apis-only","4.decisions\u002F0004-public-kyo-apis-only",{"title":131,"path":132,"stem":133},"0005. A SOFT frame contract and an own watcher loop","\u002Fdecisions\u002F0005-soft-frame-contract-and-own-watcher-loop","4.decisions\u002F0005-soft-frame-contract-and-own-watcher-loop",{"title":135,"path":136,"stem":137},"0006. Purity: edge files, lint and a pure painter","\u002Fdecisions\u002F0006-purity-edge-files-and-lint","4.decisions\u002F0006-purity-edge-files-and-lint",{"title":139,"path":140,"stem":141},"0007. Compiler flags from sbt-tpolecat","\u002Fdecisions\u002F0007-compiler-flags-from-sbt-tpolecat","4.decisions\u002F0007-compiler-flags-from-sbt-tpolecat",{"title":143,"path":144,"stem":145},"0008. The artifact split: runner, app, testkit and core","\u002Fdecisions\u002F0008-artifact-split-runner-app-testkit-core","4.decisions\u002F0008-artifact-split-runner-app-testkit-core",{"title":147,"path":148,"stem":149},"0009. tui4s-use and tui4s-widgets, cross-built","\u002Fdecisions\u002F0009-use-and-widgets-cross-built","4.decisions\u002F0009-use-and-widgets-cross-built",{"title":151,"path":152,"stem":153},"0010. The flagship assistant is the blueprint of a real app","\u002Fdecisions\u002F0010-the-flagship-assistant-as-blueprint","4.decisions\u002F0010-the-flagship-assistant-as-blueprint",{"title":155,"path":156,"stem":157},"0011. The web target: a standalone Scala.js app and one theme","\u002Fdecisions\u002F0011-web-target-standalone-scalajs-and-one-theme","4.decisions\u002F0011-web-target-standalone-scalajs-and-one-theme",{"title":159,"path":160,"stem":161},"0012. The documentation is example-first","\u002Fdecisions\u002F0012-documentation-is-example-first","4.decisions\u002F0012-documentation-is-example-first",{"title":163,"path":164,"stem":165},"0013. Benchmarks in the repository, with their own build","\u002Fdecisions\u002F0013-benchmarks-in-repo-with-own-build","4.decisions\u002F0013-benchmarks-in-repo-with-own-build",{"title":167,"path":168,"stem":169},"0014. Release per module, by tag, as 0.1.0-RC1","\u002Fdecisions\u002F0014-release-per-module-tags-and-rc1","4.decisions\u002F0014-release-per-module-tags-and-rc1",{"title":171,"path":172,"stem":173},"0015. Packaging: the AOT cache in the start scripts, native-image as an option","\u002Fdecisions\u002F0015-packaging-aot-cache-and-native-image","4.decisions\u002F0015-packaging-aot-cache-and-native-image",{"title":175,"path":176,"stem":177},"0016. Process: lean mode and agent roles","\u002Fdecisions\u002F0016-process-lean-mode-and-agent-roles","4.decisions\u002F0016-process-lean-mode-and-agent-roles",{"title":179,"path":180,"stem":181},"0017. Deferred: templates, mouse, the kitty keyboard protocol and Windows","\u002Fdecisions\u002F0017-deferred-templates-mouse-and-kitty","4.decisions\u002F0017-deferred-templates-mouse-and-kitty",{"title":183,"path":184,"stem":185},"0018. pini4s is a vendored Git submodule","\u002Fdecisions\u002F0018-pini4s-as-a-vendored-submodule","4.decisions\u002F0018-pini4s-as-a-vendored-submodule",{"title":187,"path":188,"stem":189},"0019. Upstream issues are drafts that the user posts","\u002Fdecisions\u002F0019-upstream-kyo-issues-as-drafts","4.decisions\u002F0019-upstream-kyo-issues-as-drafts",{"title":191,"path":192,"stem":193},"0020. Release from the Actions form","\u002Fdecisions\u002F0020-release-from-the-actions-form","4.decisions\u002F0020-release-from-the-actions-form",{"title":195,"path":196,"stem":197},"0021. The rulebook is CONTRIBUTING.md","\u002Fdecisions\u002F0021-the-rulebook-is-contributing-md","4.decisions\u002F0021-the-rulebook-is-contributing-md",{"title":199,"path":200,"stem":201},"0022. The logo is text","\u002Fdecisions\u002F0022-the-logo-is-text","4.decisions\u002F0022-the-logo-is-text",{"title":203,"icon":204,"path":205,"stem":206,"children":207,"page":25},"Project","i-lucide-compass","\u002Fproject","5.project",[208,213,218],{"title":209,"path":210,"stem":211,"icon":212},"Roadmap","\u002Fproject\u002Froadmap","5.project\u002F1.roadmap","i-lucide-map",{"title":214,"path":215,"stem":216,"icon":217},"Contributing","\u002Fproject\u002Fcontributing","5.project\u002F2.contributing","i-lucide-git-pull-request",{"title":219,"path":220,"stem":221,"icon":222},"Security","\u002Fproject\u002Fsecurity","5.project\u002F3.security","i-lucide-shield",{"id":224,"title":87,"body":225,"description":481,"extension":482,"links":483,"meta":484,"navigation":485,"path":88,"seo":486,"stem":89,"__hash__":487},"docs\u002F2.guide\u002F12.terminal.md",{"type":226,"value":227,"toc":476},"minimark",[228,283,294,299,363,367,370,434,448,452,465,472],[229,230,236],"pre",{"className":231,"code":232,"filename":233,"language":234,"meta":235,"style":235},"language-scala shiki shiki-themes material-theme-lighter material-theme material-theme-palenight","object CounterKyoApp extends KyoApp:\n    run(Tui.run(quit => Counter.ui(quit)))\n","CounterKyoApp.scala","scala","",[237,238,239,261],"code",{"__ignoreMap":235},[240,241,244,248,252,255,258],"span",{"class":242,"line":243},"line",1,[240,245,247],{"class":246},"sMK4o","object",[240,249,251],{"class":250},"sBMFI"," CounterKyoApp",[240,253,254],{"class":246}," extends",[240,256,257],{"class":250}," KyoApp",[240,259,260],{"class":246},":\n",[240,262,264,268,271,274,277,280],{"class":242,"line":263},2,[240,265,267],{"class":266},"sTEyZ","    run(",[240,269,270],{"class":250},"Tui",[240,272,273],{"class":266},".run(quit ",[240,275,276],{"class":246},"=>",[240,278,279],{"class":250}," Counter",[240,281,282],{"class":266},".ui(quit)))\n",[284,285,286,289,290,293],"p",{},[237,287,288],{},"Tui.run"," runs a UI in the real terminal until the UI calls its quit action. A ",[237,291,292],{},"TuiApp"," calls it for you.",[295,296,298],"h2",{"id":297},"what-the-run-changes","What the run changes",[300,301,302,315],"table",{},[303,304,305],"thead",{},[306,307,308,312],"tr",{},[309,310,311],"th",{},"When",[309,313,314],{},"What the runner does",[316,317,318,339,347,355],"tbody",{},[306,319,320,324],{},[321,322,323],"td",{},"Before the start",[321,325,326,327,330,331,334,335,338],{},"It checks that stdin is a terminal (else ",[237,328,329],{},"TuiError.NotATerminal",") and that the native library loads (else ",[237,332,333],{},"TuiError.NativeLoadFailed"," or ",[237,336,337],{},"NativeAccessDenied","). The terminal does not change before these checks.",[306,340,341,344],{},[321,342,343],{},"At the start",[321,345,346],{},"It enters raw mode and the alternate screen, hides the cursor, turns on bracketed paste, and captures the output of the JVM.",[306,348,349,352],{},[321,350,351],{},"While it runs",[321,353,354],{},"One input thread reads the keys, the pastes and the resizes. One fiber draws. A frame sends only the cells that changed. The cursor shows the caret of the focused text input.",[306,356,357,360],{},[321,358,359],{},"At the end",[321,361,362],{},"It stops the drawing, stops the input thread, leaves the alternate screen, shows the cursor, ends raw mode, and then prints the captured output.",[295,364,366],{"id":365},"each-way-that-a-run-ends","Each way that a run ends",[284,368,369],{},"The release is one stack of steps that runs once, the last acquire first. A failing step does not stop the next steps.",[300,371,372,382],{},[303,373,374],{},[306,375,376,379],{},[309,377,378],{},"The run ends by",[309,380,381],{},"The terminal",[316,383,384,398,406,414],{},[306,385,386,392],{},[321,387,388,391],{},[237,389,390],{},"Tui.quit",", or the key Ctrl-C",[321,393,394,395,397],{},"Restored. Exit code 0 in a ",[237,396,292],{},".",[306,399,400,403],{},[321,401,402],{},"A failure of the UI",[321,404,405],{},"Restored. The failure is printed after the restore.",[306,407,408,411],{},[321,409,410],{},"An interrupt of the caller",[321,412,413],{},"Restored at once.",[306,415,416,431],{},[321,417,418,421,422,421,425,421,428],{},[237,419,420],{},"kill -TERM",", ",[237,423,424],{},"kill -INT",[237,426,427],{},"kill -HUP",[237,429,430],{},"System.exit",[321,432,433],{},"The shutdown hook restores it, and waits at most 2 s.",[284,435,436,437,439,440,443,444,447],{},"After a quit, ",[237,438,288],{}," closes the ",[237,441,442],{},"Scope"," of the UI before the release: the fibers that the UI started stop first. A fiber that does not stop on an interrupt (a blocking call in ",[237,445,446],{},"Sync.defer",") keeps the terminal in raw mode until it ends.",[295,449,451],{"id":450},"limits","Limits",[453,454,455,459,462],"ul",{},[456,457,458],"li",{},"No mouse input.",[456,460,461],{},"A typed emoji arrives wrong (jatatui 0.31.0 cuts it to 16 bits). A paste keeps it.",[456,463,464],{},"CI checks the terminal path on Linux only. Windows is experimental.",[284,466,467,468,471],{},"The PTY kit checks this contract: raw mode while the app runs, the same ",[237,469,470],{},"stty -a"," before and after each run, the exit codes, and the signals.",[473,474,475],"style",{},"html pre.shiki code .sMK4o, html code.shiki .sMK4o{--shiki-light:#39ADB5;--shiki-default:#89DDFF;--shiki-dark:#89DDFF}html pre.shiki code .sBMFI, html code.shiki .sBMFI{--shiki-light:#E2931D;--shiki-default:#FFCB6B;--shiki-dark:#FFCB6B}html pre.shiki code .sTEyZ, html code.shiki .sTEyZ{--shiki-light:#90A4AE;--shiki-default:#EEFFFF;--shiki-dark:#BABED8}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}",{"title":235,"searchDepth":263,"depth":263,"links":477},[478,479,480],{"id":297,"depth":263,"text":298},{"id":365,"depth":263,"text":366},{"id":450,"depth":263,"text":451},"What the runner does to the terminal, and how each way that a run ends restores it.","md",null,{},{"icon":90},{"title":87,"description":481},"syRkRray4Z_CmY46o0glcbgt_PD62zsZBuNcv2l5jA0",[489,491],{"title":82,"path":83,"stem":84,"description":490,"icon":85,"children":-1},"The start scripts, the JVM flags, the AOT cache, a native binary, the options of a TuiApp, the exit codes and the signals.",{"title":92,"path":93,"stem":94,"description":492,"icon":95,"children":-1},"The frame-path probe of tui4s, and the bench of tui4s against seven other terminal UI stacks.",1792528752826]