mirror of
https://github.com/ArthurSonzogni/FTXUI.git
synced 2024-11-26 12:37:06 +08:00
Add webassembly support
This commit is contained in:
parent
65c0297789
commit
cac94439ff
@ -148,6 +148,13 @@ foreach(lib screen dom component)
|
|||||||
|
|
||||||
endforeach()
|
endforeach()
|
||||||
|
|
||||||
|
if (EMSCRIPTEN)
|
||||||
|
#string(APPEND CMAKE_CXX_FLAGS " -s ASSERTIONS=1")
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " -s ASYNCIFY")
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " -s USE_PTHREADS")
|
||||||
|
string(APPEND CMAKE_CXX_FLAGS " -s PROXY_TO_PTHREAD")
|
||||||
|
endif()
|
||||||
|
|
||||||
if(FTXUI_ENABLE_INSTALL)
|
if(FTXUI_ENABLE_INSTALL)
|
||||||
include(GNUInstallDirs)
|
include(GNUInstallDirs)
|
||||||
install(TARGETS screen dom component
|
install(TARGETS screen dom component
|
||||||
|
@ -72,6 +72,7 @@ A simple C++ library for terminal based user interface.
|
|||||||
|
|
||||||
- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
|
- [Starter example project](https://github.com/ArthurSonzogni/ftxui-starter)
|
||||||
- [Documentation](https://arthursonzogni.com/FTXUI/doc/)
|
- [Documentation](https://arthursonzogni.com/FTXUI/doc/)
|
||||||
|
- [Examples (WebAssembly)](https://arthursonzogni.com/FTXUI/examples/)
|
||||||
- [Build using CMake](https://arthursonzogni.com/FTXUI/doc/#build-using-cmake)
|
- [Build using CMake](https://arthursonzogni.com/FTXUI/doc/#build-using-cmake)
|
||||||
- [Build using nxxm](https://arthursonzogni.com/FTXUI/doc/#build-using-cmake)
|
- [Build using nxxm](https://arthursonzogni.com/FTXUI/doc/#build-using-cmake)
|
||||||
|
|
||||||
|
@ -1,3 +1,14 @@
|
|||||||
add_subdirectory(component)
|
add_subdirectory(component)
|
||||||
add_subdirectory(dom)
|
add_subdirectory(dom)
|
||||||
add_subdirectory(util)
|
add_subdirectory(util)
|
||||||
|
|
||||||
|
if (EMSCRIPTEN)
|
||||||
|
foreach(file
|
||||||
|
"index.html"
|
||||||
|
"run_webassembly.sh")
|
||||||
|
configure_file(
|
||||||
|
${CMAKE_CURRENT_SOURCE_DIR}/${file}
|
||||||
|
${CMAKE_CURRENT_BINARY_DIR}/${file}
|
||||||
|
)
|
||||||
|
endforeach(file)
|
||||||
|
endif()
|
||||||
|
@ -28,7 +28,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString() << std::endl;
|
screen.Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
@ -126,7 +126,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -30,7 +30,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,7 +26,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -45,7 +45,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -17,7 +17,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,7 +19,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen(100, 1);
|
auto screen = Screen(100, 1);
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << reset_position << screen.ToString() << std::flush;
|
std::cout << reset_position;
|
||||||
|
screen.Print();
|
||||||
reset_position = screen.ResetPosition();
|
reset_position = screen.ResetPosition();
|
||||||
|
|
||||||
std::this_thread::sleep_for(0.01s);
|
std::this_thread::sleep_for(0.01s);
|
||||||
|
@ -60,8 +60,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << reset_position << screen.ToString() << std::flush;
|
std::cout << reset_position;
|
||||||
|
screen.Print();
|
||||||
reset_position = screen.ResetPosition();
|
reset_position = screen.ResetPosition();
|
||||||
|
|
||||||
std::this_thread::sleep_for(0.03s);
|
std::this_thread::sleep_for(0.03s);
|
||||||
|
@ -39,7 +39,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString() << std::endl;
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -41,8 +41,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full());
|
auto screen = Screen::Create(Dimension::Full());
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << reset_position << screen.ToString() << std::flush;
|
std::cout << reset_position;
|
||||||
|
screen.Print();
|
||||||
reset_position = screen.ResetPosition();
|
reset_position = screen.ResetPosition();
|
||||||
|
|
||||||
std::this_thread::sleep_for(0.01s);
|
std::this_thread::sleep_for(0.01s);
|
||||||
|
@ -123,7 +123,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto document = render();
|
auto document = render();
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << reset_position << screen.ToString() << std::flush;
|
std::cout << reset_position;
|
||||||
|
screen.Print();
|
||||||
reset_position = screen.ResetPosition();
|
reset_position = screen.ResetPosition();
|
||||||
|
|
||||||
// Simulate time.
|
// Simulate time.
|
||||||
|
@ -25,7 +25,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Full());
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Full());
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString();
|
screen.Print();
|
||||||
getchar();
|
getchar();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -18,8 +18,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
border;
|
border;
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString() << std::endl;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -18,7 +18,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
auto document = hbox(std::move(content));
|
auto document = hbox(std::move(content));
|
||||||
auto screen = Screen::Create(Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString() << std::endl;
|
screen.Print();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -28,7 +28,8 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << reset_position << screen.ToString() << std::flush;
|
std::cout << reset_position;
|
||||||
|
screen.Print();
|
||||||
reset_position = screen.ResetPosition();
|
reset_position = screen.ResetPosition();
|
||||||
|
|
||||||
std::this_thread::sleep_for(0.1s);
|
std::this_thread::sleep_for(0.1s);
|
||||||
|
@ -12,8 +12,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -19,8 +19,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
// clang-format on
|
// clang-format on
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -11,8 +11,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -12,8 +12,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
auto screen = Screen::Create(Dimension::Full(), Dimension::Fit(document));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -26,8 +26,7 @@ int main(int argc, const char* argv[]) {
|
|||||||
});
|
});
|
||||||
auto screen = Screen::Create(Dimension::Full());
|
auto screen = Screen::Create(Dimension::Full());
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
|
screen.Print();
|
||||||
std::cout << screen.ToString();
|
|
||||||
getchar();
|
getchar();
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
@ -16,7 +16,7 @@ int main(void) {
|
|||||||
|
|
||||||
auto screen = Screen::Create(Dimension::Fixed(80), Dimension::Fixed(10));
|
auto screen = Screen::Create(Dimension::Fixed(80), Dimension::Fixed(10));
|
||||||
Render(screen, document);
|
Render(screen, document);
|
||||||
std::cout << screen.ToString() << '\n';
|
screen.Print();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
// Copyright 2020 Arthur Sonzogni. All rights reserved.
|
||||||
|
164
examples/index.html
Normal file
164
examples/index.html
Normal file
@ -0,0 +1,164 @@
|
|||||||
|
<!DOCTYPE html> <html lang="en">
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>FTXUI examples WebAssembly</title>
|
||||||
|
<script src="https://cdn.jsdelivr.net/npm/xterm@4.11.0/lib/xterm.min.js"></script>
|
||||||
|
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/xterm@4.11.0/css/xterm.css"></link>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<script id="example_script"></script>
|
||||||
|
<div class="page">
|
||||||
|
<h1>FTXUI WebAssembly Example </h1>
|
||||||
|
<p>
|
||||||
|
<a href="https://github.com/ArthurSonzogni/FTXUI">FTXUI</a> is a single
|
||||||
|
C++ library for terminal user interface.
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
On this page, you can try all the examples contained in: <a
|
||||||
|
href="https://github.com/ArthurSonzogni/FTXUI/tree/master/examples">./example/</a>
|
||||||
|
Those are compiled using WebAssembly.
|
||||||
|
</p>
|
||||||
|
<select id="selectExample"></select>
|
||||||
|
<div id="terminal"></div>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
<script>
|
||||||
|
let example_list = [
|
||||||
|
"./component/button.js",
|
||||||
|
"./component/checkbox.js",
|
||||||
|
"./component/checkbox_in_frame.js",
|
||||||
|
"./component/gallery.js",
|
||||||
|
"./component/homescreen.js",
|
||||||
|
"./component/input.js",
|
||||||
|
"./component/menu.js",
|
||||||
|
"./component/menu2.js",
|
||||||
|
"./component/menu_style.js",
|
||||||
|
"./component/radiobox.js",
|
||||||
|
"./component/radiobox_in_frame.js",
|
||||||
|
"./component/tab_horizontal.js",
|
||||||
|
"./component/tab_vertical.js",
|
||||||
|
"./component/toggle.js",
|
||||||
|
"./component/modal_dialog.js",
|
||||||
|
|
||||||
|
"./dom/border.js",
|
||||||
|
"./dom/color_gallery.js",
|
||||||
|
"./dom/dbox.js",
|
||||||
|
"./dom/gauge.js",
|
||||||
|
"./dom/graph.js",
|
||||||
|
"./dom/hflow.js",
|
||||||
|
"./dom/html_like.js",
|
||||||
|
"./dom/package_manager.js",
|
||||||
|
"./dom/paragraph.js",
|
||||||
|
"./dom/separator.js",
|
||||||
|
"./dom/size.js",
|
||||||
|
"./dom/spinner.js",
|
||||||
|
"./dom/style_blink.js",
|
||||||
|
"./dom/style_bold.js",
|
||||||
|
"./dom/style_color.js",
|
||||||
|
"./dom/color_truecolor_RGB.js",
|
||||||
|
"./dom/color_truecolor_HSV.js",
|
||||||
|
"./dom/color_info_palette256.js",
|
||||||
|
"./dom/style_dim.js",
|
||||||
|
"./dom/style_gallery.js",
|
||||||
|
"./dom/style_inverted.js",
|
||||||
|
"./dom/style_underlined.js",
|
||||||
|
"./dom/vbox_hbox.js",
|
||||||
|
"./dom/window.js",
|
||||||
|
|
||||||
|
"./util/print_key_press.js",
|
||||||
|
];
|
||||||
|
|
||||||
|
const url_search_params = new URLSearchParams(window.location.search);
|
||||||
|
const example_index = url_search_params.get("id") || 16;
|
||||||
|
const example = example_list[example_index];
|
||||||
|
|
||||||
|
var select = document.getElementById("selectExample");
|
||||||
|
|
||||||
|
for(var i = 0; i < example_list.length; i++) {
|
||||||
|
var opt = example_list[i];
|
||||||
|
var el = document.createElement("option");
|
||||||
|
el.textContent = opt;
|
||||||
|
el.value = opt;
|
||||||
|
select.appendChild(el);
|
||||||
|
}
|
||||||
|
select.selectedIndex = example_index;
|
||||||
|
select.addEventListener("change", () => {
|
||||||
|
location.href = (location.href).split('?')[0] + "?id=" + select.selectedIndex;
|
||||||
|
});
|
||||||
|
|
||||||
|
let stdin_buffer = [];
|
||||||
|
let stdin = () => {
|
||||||
|
return stdin_buffer.shift() || 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
stdout_buffer = [];
|
||||||
|
let stdout = code => {
|
||||||
|
if (code == 0) {
|
||||||
|
term.write(new Uint8Array(stdout_buffer));
|
||||||
|
stdout_buffer = [];
|
||||||
|
} else {
|
||||||
|
stdout_buffer.push(code)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
let stderr = code => console.log(code);
|
||||||
|
var term = new Terminal();
|
||||||
|
term.open(document.querySelector('#terminal'));
|
||||||
|
term.resize(140,43);
|
||||||
|
const onBinary = e => {
|
||||||
|
for(c of e)
|
||||||
|
stdin_buffer.push(c.charCodeAt(0));
|
||||||
|
}
|
||||||
|
term.onBinary(onBinary);
|
||||||
|
term.onData(onBinary)
|
||||||
|
window.Module = {
|
||||||
|
preRun: () => { FS.init(stdin, stdout, stderr); },
|
||||||
|
postRun: [],
|
||||||
|
onRuntimeInitialized: () => {},
|
||||||
|
};
|
||||||
|
document.querySelector("#example_script").src = example
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
body {
|
||||||
|
background-color:#EEE;
|
||||||
|
padding:20px;
|
||||||
|
font-family: Helvetica, sans-serif;
|
||||||
|
font-size: 130%;
|
||||||
|
}
|
||||||
|
|
||||||
|
.page {
|
||||||
|
max-width:1300px;
|
||||||
|
margin: auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
h1 {
|
||||||
|
text-decoration: underline;
|
||||||
|
}
|
||||||
|
|
||||||
|
select {
|
||||||
|
display:block;
|
||||||
|
padding: .6em 1.4em .5em .8em;
|
||||||
|
border-radius: 20px 20px 0px 0px;
|
||||||
|
font-size: 16px;
|
||||||
|
font-family: sans-serif;
|
||||||
|
font-weight: 700;
|
||||||
|
|
||||||
|
color: #444;
|
||||||
|
line-height: 1.3;
|
||||||
|
background-color:black;
|
||||||
|
border:0px;
|
||||||
|
color:white;
|
||||||
|
transition: color 0.2s linear;
|
||||||
|
transition: background-color 0.2s linear;
|
||||||
|
}
|
||||||
|
|
||||||
|
#terminal {
|
||||||
|
padding:10px;
|
||||||
|
border:none;
|
||||||
|
background-color:black;
|
||||||
|
padding:auto;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
</html>
|
6
examples/run_webassembly.sh
Executable file
6
examples/run_webassembly.sh
Executable file
@ -0,0 +1,6 @@
|
|||||||
|
#! /bin/bash
|
||||||
|
python3 -m http.server 8888 &
|
||||||
|
P1=$!
|
||||||
|
trap 'kill 0' SIGINT; P1
|
||||||
|
python3 -m webbrowser http://localhost:8888
|
||||||
|
wait $P1
|
@ -56,6 +56,7 @@ class Screen {
|
|||||||
|
|
||||||
// Convert the screen into a printable string in the terminal.
|
// Convert the screen into a printable string in the terminal.
|
||||||
std::string ToString();
|
std::string ToString();
|
||||||
|
void Print();
|
||||||
|
|
||||||
// Get screen dimensions.
|
// Get screen dimensions.
|
||||||
int dimx() { return dimx_; }
|
int dimx() { return dimx_; }
|
||||||
|
@ -38,6 +38,11 @@ namespace ftxui {
|
|||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
|
||||||
|
void Flush() {
|
||||||
|
// Emscripten doesn't implement flush. We interpret zero as flush.
|
||||||
|
std::cout << std::flush << (char)0;
|
||||||
|
}
|
||||||
|
|
||||||
constexpr int timeout_milliseconds = 20;
|
constexpr int timeout_milliseconds = 20;
|
||||||
constexpr int timeout_microseconds = timeout_milliseconds * 1000;
|
constexpr int timeout_microseconds = timeout_milliseconds * 1000;
|
||||||
#if defined(_WIN32)
|
#if defined(_WIN32)
|
||||||
@ -90,8 +95,25 @@ void EventListener(std::atomic<bool>* quit,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#else
|
#elif defined(__EMSCRIPTEN__)
|
||||||
|
#include <emscripten.h>
|
||||||
|
|
||||||
|
// Read char from the terminal.
|
||||||
|
void EventListener(std::atomic<bool>* quit, Sender<Event> out) {
|
||||||
|
(void)timeout_microseconds;
|
||||||
|
auto parser = TerminalInputParser(std::move(out));
|
||||||
|
|
||||||
|
char c;
|
||||||
|
while (!*quit) {
|
||||||
|
while(read(STDIN_FILENO, &c, 1), c)
|
||||||
|
parser.Add(c);
|
||||||
|
|
||||||
|
emscripten_sleep(1);
|
||||||
|
parser.Timeout(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
|
|
||||||
int CheckStdinReady(int usec_timeout) {
|
int CheckStdinReady(int usec_timeout) {
|
||||||
@ -260,12 +282,13 @@ void ScreenInteractive::Loop(Component* component) {
|
|||||||
// Hide the cursor and show it at exit.
|
// Hide the cursor and show it at exit.
|
||||||
std::cout << HIDE_CURSOR;
|
std::cout << HIDE_CURSOR;
|
||||||
std::cout << DISABLE_LINE_WRAP;
|
std::cout << DISABLE_LINE_WRAP;
|
||||||
std::cout << std::flush;
|
Flush();
|
||||||
on_exit_functions.push([&] {
|
on_exit_functions.push([&] {
|
||||||
std::cout << reset_cursor_position;
|
std::cout << reset_cursor_position;
|
||||||
std::cout << SHOW_CURSOR;
|
std::cout << SHOW_CURSOR;
|
||||||
std::cout << ENABLE_LINE_WRAP;
|
std::cout << ENABLE_LINE_WRAP;
|
||||||
std::cout << std::endl;
|
std::cout << std::endl;
|
||||||
|
Flush();
|
||||||
});
|
});
|
||||||
|
|
||||||
auto event_listener =
|
auto event_listener =
|
||||||
@ -276,7 +299,8 @@ void ScreenInteractive::Loop(Component* component) {
|
|||||||
if (!event_receiver_->HasPending()) {
|
if (!event_receiver_->HasPending()) {
|
||||||
std::cout << reset_cursor_position << ResetPosition();
|
std::cout << reset_cursor_position << ResetPosition();
|
||||||
Draw(component);
|
Draw(component);
|
||||||
std::cout << ToString() << set_cursor_position << std::flush;
|
std::cout << ToString() << set_cursor_position;
|
||||||
|
Flush();
|
||||||
Clear();
|
Clear();
|
||||||
}
|
}
|
||||||
Event event;
|
Event event;
|
||||||
|
@ -42,7 +42,7 @@ TEST(TextTest, ScreenBigger2) {
|
|||||||
Screen screen(6, 2);
|
Screen screen(6, 2);
|
||||||
Render(screen, element);
|
Render(screen, element);
|
||||||
|
|
||||||
EXPECT_EQ("test \n ", screen.ToString());
|
EXPECT_EQ("test \r\n ", screen.ToString());
|
||||||
}
|
}
|
||||||
|
|
||||||
// See https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-504871456
|
// See https://github.com/ArthurSonzogni/FTXUI/issues/2#issuecomment-504871456
|
||||||
@ -51,8 +51,8 @@ TEST(TextTest, CJK) {
|
|||||||
Screen screen(6, 3);
|
Screen screen(6, 3);
|
||||||
Render(screen, element);
|
Render(screen, element);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"┌────┐\n"
|
"┌────┐\r\n"
|
||||||
"│测试│\n"
|
"│测试│\r\n"
|
||||||
"└────┘",
|
"└────┘",
|
||||||
screen.ToString());
|
screen.ToString());
|
||||||
}
|
}
|
||||||
@ -63,8 +63,8 @@ TEST(TextTest, CJK_2) {
|
|||||||
Screen screen(5, 3);
|
Screen screen(5, 3);
|
||||||
Render(screen, element);
|
Render(screen, element);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"┌───┐\n"
|
"┌───┐\r\n"
|
||||||
"│测试\n"
|
"│测试\r\n"
|
||||||
"└───┘",
|
"└───┘",
|
||||||
screen.ToString());
|
screen.ToString());
|
||||||
}
|
}
|
||||||
@ -75,8 +75,8 @@ TEST(TextTest, CJK_3) {
|
|||||||
Screen screen(4, 3);
|
Screen screen(4, 3);
|
||||||
Render(screen, element);
|
Render(screen, element);
|
||||||
EXPECT_EQ(
|
EXPECT_EQ(
|
||||||
"┌──┐\n"
|
"┌──┐\r\n"
|
||||||
"│测│\n"
|
"│测│\r\n"
|
||||||
"└──┘",
|
"└──┘",
|
||||||
screen.ToString());
|
screen.ToString());
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ using namespace ftxui;
|
|||||||
using namespace ftxui;
|
using namespace ftxui;
|
||||||
|
|
||||||
std::string rotate(std::string str) {
|
std::string rotate(std::string str) {
|
||||||
|
str.erase(std::remove(str.begin(), str.end(), '\r'), str.end());
|
||||||
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
|
str.erase(std::remove(str.begin(), str.end(), '\n'), str.end());
|
||||||
return str;
|
return str;
|
||||||
}
|
}
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <sstream>
|
#include <sstream>
|
||||||
|
#include <iostream>
|
||||||
|
|
||||||
#include "ftxui/dom/node.hpp"
|
#include "ftxui/dom/node.hpp"
|
||||||
#include "ftxui/screen/string.hpp"
|
#include "ftxui/screen/string.hpp"
|
||||||
@ -149,6 +150,7 @@ Screen::Screen(int dimx, int dimy)
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Produce a std::string that can be used to print the Screen on the terminal.
|
/// Produce a std::string that can be used to print the Screen on the terminal.
|
||||||
|
/// Don't forget to flush stdout. Alternatively, you can use Screen::Print();
|
||||||
std::string Screen::ToString() {
|
std::string Screen::ToString() {
|
||||||
std::wstringstream ss;
|
std::wstringstream ss;
|
||||||
|
|
||||||
@ -158,7 +160,7 @@ std::string Screen::ToString() {
|
|||||||
for (int y = 0; y < dimy_; ++y) {
|
for (int y = 0; y < dimy_; ++y) {
|
||||||
if (y != 0) {
|
if (y != 0) {
|
||||||
UpdatePixelStyle(ss, previous_pixel, final_pixel);
|
UpdatePixelStyle(ss, previous_pixel, final_pixel);
|
||||||
ss << '\n';
|
ss << L"\r\n";
|
||||||
}
|
}
|
||||||
for (int x = 0; x < dimx_;) {
|
for (int x = 0; x < dimx_;) {
|
||||||
auto& pixel = pixels_[y][x];
|
auto& pixel = pixels_[y][x];
|
||||||
@ -181,6 +183,10 @@ std::string Screen::ToString() {
|
|||||||
return to_string(ss.str());
|
return to_string(ss.str());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void Screen::Print() {
|
||||||
|
std::cout << ToString() << std::flush << (char)0;
|
||||||
|
}
|
||||||
|
|
||||||
/// @brief Access a character a given position.
|
/// @brief Access a character a given position.
|
||||||
/// @param x The character position along the x-axis.
|
/// @param x The character position along the x-axis.
|
||||||
/// @param y The character position along the y-axis.
|
/// @param y The character position along the y-axis.
|
||||||
@ -254,6 +260,7 @@ void Screen::ApplyShader() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
||||||
} // namespace ftxui
|
} // namespace ftxui
|
||||||
|
@ -19,7 +19,7 @@ namespace ftxui {
|
|||||||
|
|
||||||
Terminal::Dimensions Terminal::Size() {
|
Terminal::Dimensions Terminal::Size() {
|
||||||
#if defined(__EMSCRIPTEN__)
|
#if defined(__EMSCRIPTEN__)
|
||||||
return Dimensions{80, 43};
|
return Dimensions{140, 43};
|
||||||
#elif defined(_WIN32)
|
#elif defined(_WIN32)
|
||||||
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
CONSOLE_SCREEN_BUFFER_INFO csbi;
|
||||||
int columns, rows;
|
int columns, rows;
|
||||||
@ -48,6 +48,10 @@ bool Contains(const std::string& s, const char* key) {
|
|||||||
static bool cached = false;
|
static bool cached = false;
|
||||||
Terminal::Color cached_supported_color;
|
Terminal::Color cached_supported_color;
|
||||||
Terminal::Color ComputeColorSupport() {
|
Terminal::Color ComputeColorSupport() {
|
||||||
|
#if defined(__EMSCRIPTEN__)
|
||||||
|
return Terminal::Color::TrueColor;
|
||||||
|
#endif
|
||||||
|
|
||||||
std::string COLORTERM = Safe(std::getenv("COLORTERM"));
|
std::string COLORTERM = Safe(std::getenv("COLORTERM"));
|
||||||
if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor"))
|
if (Contains(COLORTERM, "24bit") || Contains(COLORTERM, "truecolor"))
|
||||||
return Terminal::Color::TrueColor;
|
return Terminal::Color::TrueColor;
|
||||||
|
Loading…
Reference in New Issue
Block a user