新增功能:处理平台与终端特定的特性

This commit is contained in:
keqingmoe 2024-12-13 10:47:50 +08:00
parent e7ed992aee
commit 328853740f
4 changed files with 165 additions and 3 deletions

View File

@ -0,0 +1,63 @@
/**
* @file tui/plat/color_depth.cppm
* @brief 获取终端支持的色彩深度
* @author KeqingMoe
* @date 2024-12-13
* @copyright Copyright (c) 2024 KeqingMoe
* @license MIT License
*/
export module kqm.tui.plat:color_depth;
import std;
auto get_env(const char* env_var) noexcept -> std::string_view
{
auto env = std::getenv(env_var);
if (!env) return std::string_view{};
return std::string_view{env};
}
export namespace kqm::tui
{
inline namespace plat
{
/**
* @brief 获取当前终端支持的色彩深度
*
* @return `std::size_t` 色彩深度
* @retval `4uz` 16 色
* @retval `8uz` 256 色
* @retval `24uz` 24 bits 真彩色
*/
auto get_color_depth() noexcept -> std::size_t
{
#ifdef __EMSCRIPTEN__
return 24uz;
#else
// Windows Terminal 支持 24bits 真彩色
if (std::getenv("WT_SESSION")) {
return 24uz;
}
auto env_colorterm = get_env("COLORTERM");
if (env_colorterm.contains("24bit") || env_colorterm.contains("truecolor")) {
return 24uz;
}
auto env_term = get_env("TERM");
if (env_colorterm.contains("256") || env_term.contains("256")) {
return 8uz;
}
#endif
return 4uz;
}
/**
* @brief 已缓存的色彩深度
*/
auto color_depth = get_color_depth();
}
}

View File

@ -1,5 +1,5 @@
/**
* @file tui/screen/colors.cppm
* @file tui/plat/colors.cppm
* @brief 预定义的颜色常量
* @author KeqingMoe
* @date 2024-12-9
@ -7,14 +7,14 @@
* @license MIT License
*/
export module kqm.tui.screen:colors;
export module kqm.tui.plat:colors;
import std;
export namespace kqm::tui
{
inline namespace screen
inline namespace plat
{
inline namespace colors

15
src/tui/plat/plat.cppm Normal file
View File

@ -0,0 +1,15 @@
/**
* @file tui/plat/plat.cppm
* @brief 获取依赖于终端的信息和依赖于平台的代码
* @details 相关实现分散在各个模块分区内,并隔离了相关的宏和无关名,这个文件只负责汇总导出接口
* @author KeqingMoe
* @date 2024-12-11
* @copyright Copyright (c) 2024 KeqingMoe
* @license MIT License
*/
export module kqm.tui.plat;
export import :colors;
export import :color_depth;
export import :size;

84
src/tui/plat/size.cppm Normal file
View File

@ -0,0 +1,84 @@
/**
* @file tui/plat/size.cppm
* @brief 获取终端的宽度与高度
* @author KeqingMoe
* @date 2024-12-13
* @copyright Copyright (c) 2024 KeqingMoe
* @license MIT License
*/
module;
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#ifndef NOMINMAX
#define NOMINMAX
#endif
#include <windows.h>
#else
#include <sys/ioctl.h> // for winsize, ioctl, TIOCGWINSZ
#include <unistd.h> // for STDOUT_FILENO
#endif
export module kqm.tui.plat:size;
import std;
export namespace kqm::tui
{
inline namespace plat
{
/**
* @brief 用作回退值的终端大小first 是宽second 是高
*/
auto fallback_terminal_size = std::pair{
#ifdef __EMSCRIPTEN__
140uz, 43uz
#else
80uz, 24uz
#endif
};
/**
* @brief 获取当前终端的大小
*
* @return `std::pair<std::size_t, std::size_t>` first 是宽second 是高
*/
auto get_terminal_size() -> std::pair<std::size_t, std::size_t>
{
#if defined(__EMSCRIPTEN___)
return fallback_size;
#elif defined(_WIN32)
auto csbi = CONSOLE_SCREEN_BUFFER_INFO{};
auto handle = GetStdHandle(STD_OUTPUT_HANDLE);
auto flag = GetConsoleScreenBufferInfo(handle, &csbi);
if (flag) {
auto width = csbi.srWindow.Right - csbi.srWindow.Left + 1uz;
auto height = csbi.srWindow.Bottom - csbi.srWindow.Top + 1uz;
return std::pair{width, height};
}
return fallback_terminal_size;
#else
auto w = winsize{};
auto status = ioctl(STDOUT_FILENO, TIOCGWINSZ, &w);
auto width = std::size_t{w.ws_col};
auto height = std::size_t{w.ws_row};
if (width == 0 || height == 0 || status < 0) {
return fallback_size;
}
return std::pair{width, height};
#endif
}
}
}