TerminalSize: add new module

This commit is contained in:
李通洲
2023-07-26 10:27:40 +08:00
committed by 李通洲
parent 2f0d0a5a02
commit 8cbeb709f9
20 changed files with 279 additions and 17 deletions
+2 -4
View File
@@ -83,10 +83,8 @@ typedef enum FFPathType
bool ffPathExists(const char* path, FFPathType pathType);
#ifndef _WIN32
FF_C_SCANF(2, 3)
void ffGetTerminalResponse(const char* request, const char* format, ...);
#endif
FF_C_SCANF(2, 3)
const char* ffGetTerminalResponse(const char* request, const char* format, ...);
// Not thread safe!
bool ffSuppressIO(bool suppress);
+8 -11
View File
@@ -107,30 +107,25 @@ bool ffPathExists(const char* path, FFPathType type)
return false;
}
void ffGetTerminalResponse(const char* request, const char* format, ...)
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
{
struct termios oldTerm, newTerm;
if(tcgetattr(STDIN_FILENO, &oldTerm) == -1)
return;
return "tcgetattr(STDIN_FILENO, &oldTerm) failed";
newTerm = oldTerm;
newTerm.c_lflag &= (tcflag_t) ~(ICANON | ECHO);
if(tcsetattr(STDIN_FILENO, TCSANOW, &newTerm) == -1)
return;
return "tcsetattr(STDIN_FILENO, TCSANOW, &newTerm)";
fputs(request, stdout);
fflush(stdout);
struct pollfd pfd;
pfd.fd = STDIN_FILENO;
pfd.events = POLLIN;
pfd.revents = 0;
//Give the terminal 35ms to respond
if(poll(&pfd, 1, 35) <= 0)
if(poll(&(struct pollfd) { .fd = STDIN_FILENO, .events = POLLIN }, 1, 35) <= 0)
{
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
return;
return "poll() timeout or failed";
}
char buffer[512];
@@ -139,7 +134,7 @@ void ffGetTerminalResponse(const char* request, const char* format, ...)
tcsetattr(STDIN_FILENO, TCSANOW, &oldTerm);
if(readed <= 0)
return;
return "read(STDIN_FILENO, buffer, sizeof(buffer) - 1) failed";
buffer[readed] = '\0';
@@ -147,6 +142,8 @@ void ffGetTerminalResponse(const char* request, const char* format, ...)
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
return NULL;
}
bool ffSuppressIO(bool suppress)
+57
View File
@@ -1,6 +1,8 @@
#include "io.h"
#include "util/stringUtils.h"
#include <windows.h>
static void createSubfolders(const char* fileName)
{
FF_STRBUF_AUTO_DESTROY path = ffStrbufCreate();
@@ -144,3 +146,58 @@ void ffListFilesRecursively(const char* path)
ffStrbufEnsureEndsWithC(&folder, '/');
listFilesRecursively(&folder, 0, NULL);
}
const char* ffGetTerminalResponse(const char* request, const char* format, ...)
{
HANDLE hInput = GetStdHandle(STD_INPUT_HANDLE);
DWORD prev_mode;
GetConsoleMode(hInput, &prev_mode);
SetConsoleMode(hInput, 0);
FlushConsoleInputBuffer(hInput);
DWORD bytes = 0;
WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), request, (DWORD) strlen(request), &bytes, NULL);
while (true)
{
if (WaitForSingleObjectEx(hInput, 35, TRUE) != WAIT_OBJECT_0)
{
SetConsoleMode(hInput, prev_mode);
return "WaitForSingleObject() failed or timeout";
}
// Ignore all unexpected input events
INPUT_RECORD record;
DWORD len = 0;
if (!PeekConsoleInputW(hInput, &record, 1, &len))
break;
if (
record.EventType == KEY_EVENT &&
record.Event.KeyEvent.uChar.UnicodeChar != L'\r' &&
record.Event.KeyEvent.uChar.UnicodeChar != L'\n'
)
break;
else
ReadConsoleInputW(hInput, &record, 1, &len);
}
char buffer[512];
bytes = 0;
ReadFile(hInput, buffer, sizeof(buffer) - 1, &bytes, NULL);
SetConsoleMode(hInput, prev_mode);
if(bytes <= 0)
return "ReadFile() failed";
buffer[bytes] = '\0';
va_list args;
va_start(args, format);
vsscanf(buffer, format, args);
va_end(args);
return NULL;
}
+1
View File
@@ -188,6 +188,7 @@ static bool parseModuleJsonObject(const char* type, yyjson_val* module)
return
tryModule(type, module, FF_TERMINAL_MODULE_NAME, ffParseTerminalJsonObject) ||
tryModule(type, module, FF_TERMINALFONT_MODULE_NAME, ffParseTerminalFontJsonObject) ||
tryModule(type, module, FF_TERMINALSIZE_MODULE_NAME, ffParseTerminalSizeJsonObject) ||
tryModule(type, module, FF_TITLE_MODULE_NAME, ffParseTitleJsonObject) ||
tryModule(type, module, FF_THEME_MODULE_NAME, ffParseThemeJsonObject) ||
false;
+18
View File
@@ -0,0 +1,18 @@
#pragma once
#ifndef FF_INCLUDED_detection_terminalsize_terminalsize
#define FF_INCLUDED_detection_terminalsize_terminalsize
#include "fastfetch.h"
typedef struct FFTerminalSizeResult
{
uint16_t rows;
uint16_t columns;
uint16_t width;
uint16_t height;
} FFTerminalSizeResult;
bool ffDetectTerminalSize(FFTerminalSizeResult* result);
#endif
@@ -0,0 +1,26 @@
#include "terminalsize.h"
#include "common/io/io.h"
#include <sys/ioctl.h>
#include <unistd.h>
bool ffDetectTerminalSize(FFTerminalSizeResult* result)
{
struct winsize winsize = {};
ioctl(STDOUT_FILENO, TIOCGWINSZ, &winsize);
if (winsize.ws_row == 0 || winsize.ws_col == 0)
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &winsize.ws_row, &winsize.ws_col);
if (winsize.ws_ypixel == 0 || winsize.ws_xpixel == 0)
ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &winsize.ws_ypixel, &winsize.ws_xpixel);
if (winsize.ws_row == 0 && winsize.ws_col == 0)
return false;
result->rows = winsize.ws_row;
result->columns = winsize.ws_col;
result->width = winsize.ws_xpixel;
result->height = winsize.ws_ypixel;
return true;
}
@@ -0,0 +1,41 @@
#include "terminalsize.h"
#include "common/io/io.h"
#include <windows.h>
bool ffDetectTerminalSize(FFTerminalSizeResult* result)
{
{
CONSOLE_SCREEN_BUFFER_INFO csbi;
if (GetConsoleScreenBufferInfo(GetStdHandle(STD_OUTPUT_HANDLE), &csbi))
{
result->columns = (uint16_t) (csbi.srWindow.Right - csbi.srWindow.Left + 1);
result->rows = (uint16_t) (csbi.srWindow.Bottom - csbi.srWindow.Top + 1);
}
else
{
ffGetTerminalResponse("\033[18t", "\033[8;%hu;%hut", &result->rows, &result->columns);
}
}
if (result->columns == 0 && result->rows == 0)
return false;
{
CONSOLE_FONT_INFO cfi;
if(GetCurrentConsoleFont(GetStdHandle(STD_OUTPUT_HANDLE), FALSE, &cfi)) // Only works for ConHost
{
result->width = result->columns * (uint16_t) cfi.dwFontSize.X;
result->height = result->rows * (uint16_t) cfi.dwFontSize.Y;
}
else
{
// Pending https://github.com/microsoft/terminal/issues/8581
// if (result->width == 0 && result->height == 0)
// ffGetTerminalResponse("\033[14t", "\033[4;%hu;%hut", &result->height, &result->width);
return false;
}
}
return result->columns > 0 && result->rows > 0;
}
+3
View File
@@ -971,6 +971,7 @@ static void parseOption(FFdata* data, const char* key, const char* value)
else if(ffParseCursorCommandOptions(&instance.config.cursor, key, value)) {}
else if(ffParseTerminalCommandOptions(&instance.config.terminal, key, value)) {}
else if(ffParseTerminalFontCommandOptions(&instance.config.terminalFont, key, value)) {}
else if(ffParseTerminalSizeCommandOptions(&instance.config.terminalSize, key, value)) {}
else if(ffParseCPUCommandOptions(&instance.config.cpu, key, value)) {}
else if(ffParseCPUUsageCommandOptions(&instance.config.cpuUsage, key, value)) {}
else if(ffParseGPUCommandOptions(&instance.config.gpu, key, value)) {}
@@ -1182,6 +1183,8 @@ static void parseStructureCommand(const char* line, FFlist* customValues)
ffPrintTerminal(&instance.config.terminal);
else if(ffStrEqualsIgnCase(line, FF_TERMINALFONT_MODULE_NAME))
ffPrintTerminalFont(&instance.config.terminalFont);
else if(ffStrEqualsIgnCase(line, FF_TERMINALSIZE_MODULE_NAME))
ffPrintTerminalSize(&instance.config.terminalSize);
else if(ffStrEqualsIgnCase(line, FF_CPU_MODULE_NAME))
ffPrintCPU(&instance.config.cpu);
else if(ffStrEqualsIgnCase(line, FF_CPUUSAGE_MODULE_NAME))
+1
View File
@@ -82,6 +82,7 @@ typedef struct FFconfig
FFCursorOptions cursor;
FFTerminalOptions terminal;
FFTerminalFontOptions terminalFont;
FFTerminalSizeOptions terminalSize;
FFCPUOptions cpu;
FFCPUUsageOptions cpuUsage;
FFCustomOptions custom;
+1
View File
@@ -44,6 +44,7 @@
#include "modules/swap/swap.h"
#include "modules/terminal/terminal.h"
#include "modules/terminalfont/terminalfont.h"
#include "modules/terminalsize/terminalsize.h"
#include "modules/theme/theme.h"
#include "modules/title/title.h"
#include "modules/uptime/uptime.h"
+1
View File
@@ -43,6 +43,7 @@
#include "modules/swap/option.h"
#include "modules/terminal/option.h"
#include "modules/terminalfont/option.h"
#include "modules/terminalsize/option.h"
#include "modules/theme/option.h"
#include "modules/title/option.h"
#include "modules/uptime/option.h"
+11
View File
@@ -0,0 +1,11 @@
#pragma once
// This file will be included in "fastfetch.h", do NOT put unnecessary things here
#include "common/option.h"
typedef struct FFTerminalSizeOptions
{
const char* moduleName;
FFModuleArgs moduleArgs;
} FFTerminalSizeOptions;
+86
View File
@@ -0,0 +1,86 @@
#include "common/printing.h"
#include "common/jsonconfig.h"
#include "detection/terminalsize/terminalsize.h"
#include "modules/terminalsize/terminalsize.h"
#include "util/stringUtils.h"
#define FF_TERMINALSIZE_DISPLAY_NAME "Terminal Size"
#define FF_TERMINALSIZE_NUM_FORMAT_ARGS 4
void ffPrintTerminalSize(FFTerminalSizeOptions* options)
{
FFTerminalSizeResult result = {};
if(!ffDetectTerminalSize(&result))
{
ffPrintError(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, "Failed to detect terminal size");
}
else
{
if(options->moduleArgs.outputFormat.length == 0)
{
ffPrintLogoAndKey(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs.key, &options->moduleArgs.keyColor);
printf("%u columns x %u rows", result.columns, result.rows);
if (result.width != 0 && result.height != 0)
printf(" (%upx x %upx)", result.width, result.height);
putchar('\n');
}
else
{
ffPrintFormat(FF_TERMINALSIZE_DISPLAY_NAME, 0, &options->moduleArgs, FF_TERMINALSIZE_NUM_FORMAT_ARGS, (FFformatarg[]){
{FF_FORMAT_ARG_TYPE_UINT16, &result.rows},
{FF_FORMAT_ARG_TYPE_UINT16, &result.columns},
{FF_FORMAT_ARG_TYPE_UINT16, &result.width},
{FF_FORMAT_ARG_TYPE_UINT16, &result.height}
});
}
}
}
void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options)
{
options->moduleName = FF_TERMINALSIZE_MODULE_NAME;
ffOptionInitModuleArg(&options->moduleArgs);
}
bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value)
{
const char* subKey = ffOptionTestPrefix(key, FF_TERMINALSIZE_MODULE_NAME);
if (!subKey) return false;
if (ffOptionParseModuleArgs(key, subKey, value, &options->moduleArgs))
return true;
return false;
}
void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options)
{
ffOptionDestroyModuleArg(&options->moduleArgs);
}
void ffParseTerminalSizeJsonObject(yyjson_val* module)
{
FFTerminalSizeOptions __attribute__((__cleanup__(ffDestroyTerminalSizeOptions))) options;
ffInitTerminalSizeOptions(&options);
if (module)
{
yyjson_val *key_, *val;
size_t idx, max;
yyjson_obj_foreach(module, idx, max, key_, val)
{
const char* key = yyjson_get_str(key_);
if(ffStrEqualsIgnCase(key, "type"))
continue;
if (ffJsonConfigParseModuleArgs(key, val, &options.moduleArgs))
continue;
ffPrintError(FF_TERMINALSIZE_MODULE_NAME, 0, &options.moduleArgs, "Unknown JSON key %s", key);
}
}
ffPrintTerminalSize(&options);
}
+11
View File
@@ -0,0 +1,11 @@
#pragma once
#include "fastfetch.h"
#define FF_TERMINALSIZE_MODULE_NAME "TerminalSize"
void ffPrintTerminalSize(FFTerminalSizeOptions* options);
void ffInitTerminalSizeOptions(FFTerminalSizeOptions* options);
bool ffParseTerminalSizeCommandOptions(FFTerminalSizeOptions* options, const char* key, const char* value);
void ffDestroyTerminalSizeOptions(FFTerminalSizeOptions* options);
void ffParseTerminalSizeJsonObject(yyjson_val* module);