mirror of
https://oauth2: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@github.com/m1ngsama/TNT.git
synced 2026-06-26 05:34:39 +08:00
exec: extract help text into catalog
This commit is contained in:
parent
5eda6ed127
commit
e911a2d469
13 changed files with 116 additions and 36 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -15,6 +15,7 @@ tests/unit/test_history_view
|
|||
tests/unit/test_i18n
|
||||
tests/unit/test_system_message
|
||||
tests/unit/test_command_catalog
|
||||
tests/unit/test_exec_catalog
|
||||
tests/unit/test_help_text
|
||||
tests/unit/test_manual_text
|
||||
tests/unit/test_support_text
|
||||
|
|
|
|||
|
|
@ -251,6 +251,9 @@ TNT/
|
|||
│ ├── main.c # entry point
|
||||
│ ├── cli_text.c # startup CLI help and option text
|
||||
│ ├── command_catalog.c # command metadata
|
||||
│ ├── commands.c # COMMAND-mode command dispatch
|
||||
│ ├── exec_catalog.c # SSH exec command metadata
|
||||
│ ├── exec.c # SSH exec command dispatch
|
||||
│ ├── ssh_server.c # SSH server implementation
|
||||
│ ├── bootstrap.c # SSH authentication and session bootstrap
|
||||
│ ├── chat_room.c # chat room logic
|
||||
|
|
|
|||
|
|
@ -12,6 +12,8 @@
|
|||
message" / "私信" instead of mixing it with "whisper" wording.
|
||||
- Kept localized startup CLI syntax stable by using `用法: tnt [options]`
|
||||
instead of localizing the `[options]` metavariable.
|
||||
- Moved SSH exec help rows into an `exec_catalog` module so command metadata
|
||||
no longer lives as one large translated blob inside the shared i18n table.
|
||||
- Renamed the internal language state from help-oriented names to
|
||||
UI-language names (`ui_lang_t`, `client->ui_lang`, and
|
||||
`i18n_*_ui_lang`) so future i18n work has a correctly named seam.
|
||||
|
|
|
|||
|
|
@ -74,6 +74,7 @@ src/
|
|||
├── input.c - Interactive session loop and key handling
|
||||
├── commands.c - COMMAND-mode command dispatch
|
||||
├── command_catalog.c - COMMAND-mode names, aliases, and help summaries
|
||||
├── exec_catalog.c - SSH exec command help metadata
|
||||
├── exec.c - SSH exec command dispatch
|
||||
├── chat_room.c - Chat room logic and message broadcasting
|
||||
├── message.c - Message persistence (RFC3339 format)
|
||||
|
|
|
|||
|
|
@ -51,6 +51,7 @@ STRUCTURE
|
|||
src/bootstrap.c SSH auth/session bootstrap
|
||||
src/chat_room.c broadcast and room state
|
||||
src/commands.c COMMAND-mode command dispatch
|
||||
src/exec_catalog.c SSH exec command metadata
|
||||
src/exec.c SSH exec command dispatch
|
||||
src/message.c persistence, search
|
||||
src/history_view.c message viewport / scroll state
|
||||
|
|
|
|||
9
include/exec_catalog.h
Normal file
9
include/exec_catalog.h
Normal file
|
|
@ -0,0 +1,9 @@
|
|||
#ifndef EXEC_CATALOG_H
|
||||
#define EXEC_CATALOG_H
|
||||
|
||||
#include "common.h"
|
||||
|
||||
void exec_catalog_append_help(char *buffer, size_t buf_size, size_t *pos,
|
||||
ui_lang_t lang);
|
||||
|
||||
#endif /* EXEC_CATALOG_H */
|
||||
|
|
@ -53,7 +53,6 @@ typedef enum {
|
|||
I18N_UNKNOWN_COMMAND_FORMAT,
|
||||
I18N_DID_YOU_MEAN_FORMAT,
|
||||
I18N_UNKNOWN_GUIDANCE,
|
||||
I18N_EXEC_HELP,
|
||||
I18N_EXEC_USERS_USAGE,
|
||||
I18N_EXEC_STATS_USAGE,
|
||||
I18N_EXEC_TAIL_USAGE,
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#include "chat_room.h"
|
||||
#include "client.h"
|
||||
#include "common.h"
|
||||
#include "exec_catalog.h"
|
||||
#include "i18n.h"
|
||||
#include "input.h"
|
||||
#include "message.h"
|
||||
|
|
@ -116,9 +117,13 @@ static void resolve_exec_username(const client_t *client, char *buffer,
|
|||
}
|
||||
|
||||
static int exec_command_help(client_t *client) {
|
||||
const char *help_text = i18n_text(client->ui_lang, I18N_EXEC_HELP);
|
||||
char help_text[1024];
|
||||
size_t pos = 0;
|
||||
|
||||
return client_send(client, help_text, strlen(help_text)) == 0 ? 0 : 1;
|
||||
help_text[0] = '\0';
|
||||
exec_catalog_append_help(help_text, sizeof(help_text), &pos,
|
||||
client->ui_lang);
|
||||
return client_send(client, help_text, pos) == 0 ? 0 : 1;
|
||||
}
|
||||
|
||||
static int exec_command_health(client_t *client) {
|
||||
|
|
|
|||
35
src/exec_catalog.c
Normal file
35
src/exec_catalog.c
Normal file
|
|
@ -0,0 +1,35 @@
|
|||
#include "exec_catalog.h"
|
||||
|
||||
typedef struct {
|
||||
const char *usage;
|
||||
const char *summary_en;
|
||||
const char *summary_zh;
|
||||
} exec_catalog_entry_t;
|
||||
|
||||
static const exec_catalog_entry_t entries[] = {
|
||||
{"help", "Show this help", "显示此帮助"},
|
||||
{"health", "Print service health", "输出服务健康状态"},
|
||||
{"users [--json]", "List online users", "列出在线用户"},
|
||||
{"stats [--json]", "Print room statistics", "输出房间统计"},
|
||||
{"tail [N]", "Print recent messages", "输出最近消息"},
|
||||
{"tail -n N", "Print recent messages", "输出最近消息"},
|
||||
{"post MESSAGE", "Post a message non-interactively", "非交互发送消息"},
|
||||
{"post \"/me act\"", "Post an action message", "发送动作消息"},
|
||||
{"exit", "Exit successfully", "成功退出"}
|
||||
};
|
||||
|
||||
void exec_catalog_append_help(char *buffer, size_t buf_size, size_t *pos,
|
||||
ui_lang_t lang) {
|
||||
if (lang == UI_LANG_ZH) {
|
||||
buffer_appendf(buffer, buf_size, pos, "TNT exec 接口\n命令:\n");
|
||||
} else {
|
||||
buffer_appendf(buffer, buf_size, pos, "TNT exec interface\nCommands:\n");
|
||||
}
|
||||
|
||||
for (size_t i = 0; i < sizeof(entries) / sizeof(entries[0]); i++) {
|
||||
const char *summary = lang == UI_LANG_ZH ? entries[i].summary_zh
|
||||
: entries[i].summary_en;
|
||||
buffer_appendf(buffer, buf_size, pos, " %-15s %s\n",
|
||||
entries[i].usage, summary);
|
||||
}
|
||||
}
|
||||
|
|
@ -208,30 +208,6 @@ static const i18n_text_entry_t text_catalog[I18N_TEXT_COUNT] = {
|
|||
"Type :help for help\n",
|
||||
"输入 :help 查看帮助\n"
|
||||
},
|
||||
[I18N_EXEC_HELP] = {
|
||||
"TNT exec interface\n"
|
||||
"Commands:\n"
|
||||
" help Show this help\n"
|
||||
" health Print service health\n"
|
||||
" users [--json] List online users\n"
|
||||
" stats [--json] Print room statistics\n"
|
||||
" tail [N] Print recent messages\n"
|
||||
" tail -n N Print recent messages\n"
|
||||
" post MESSAGE Post a message non-interactively\n"
|
||||
" post \"/me act\" Post an action message\n"
|
||||
" exit Exit successfully\n",
|
||||
"TNT exec 接口\n"
|
||||
"命令:\n"
|
||||
" help 显示此帮助\n"
|
||||
" health 输出服务健康状态\n"
|
||||
" users [--json] 列出在线用户\n"
|
||||
" stats [--json] 输出房间统计\n"
|
||||
" tail [N] 输出最近消息\n"
|
||||
" tail -n N 输出最近消息\n"
|
||||
" post MESSAGE 非交互发送消息\n"
|
||||
" post \"/me act\" 发送动作消息\n"
|
||||
" exit 成功退出\n"
|
||||
},
|
||||
[I18N_EXEC_USERS_USAGE] = {
|
||||
"users: usage: users [--json]\n",
|
||||
"users: 用法: users [--json]\n"
|
||||
|
|
|
|||
|
|
@ -19,12 +19,13 @@ CHAT_ROOM_SRC = ../../src/chat_room.c
|
|||
HISTORY_VIEW_SRC = ../../src/history_view.c
|
||||
I18N_SRC = ../../src/i18n.c
|
||||
I18N_TEXT_SRC = ../../src/i18n_text.c
|
||||
EXEC_CATALOG_SRC = ../../src/exec_catalog.c
|
||||
SYSTEM_MESSAGE_SRC = ../../src/system_message.c
|
||||
HELP_TEXT_SRC = ../../src/help_text.c
|
||||
MANUAL_TEXT_SRC = ../../src/manual_text.c
|
||||
RATELIMIT_SRC = ../../src/ratelimit.c
|
||||
|
||||
TESTS = test_utf8 test_message test_chat_room test_history_view test_i18n test_system_message test_command_catalog test_help_text test_manual_text test_cli_text test_ratelimit
|
||||
TESTS = test_utf8 test_message test_chat_room test_history_view test_i18n test_system_message test_command_catalog test_exec_catalog test_help_text test_manual_text test_cli_text test_ratelimit
|
||||
|
||||
.PHONY: all clean run
|
||||
|
||||
|
|
@ -51,6 +52,9 @@ test_system_message: test_system_message.c $(SYSTEM_MESSAGE_SRC) $(I18N_SRC) $(I
|
|||
test_command_catalog: test_command_catalog.c $(COMMAND_CATALOG_SRC) $(COMMON_SRC)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_exec_catalog: test_exec_catalog.c $(EXEC_CATALOG_SRC) $(COMMON_SRC)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
test_help_text: test_help_text.c $(HELP_TEXT_SRC) $(COMMAND_CATALOG_SRC) $(COMMON_SRC)
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS)
|
||||
|
||||
|
|
@ -85,6 +89,9 @@ run: all
|
|||
@echo "=== Running Command Catalog Tests ==="
|
||||
./test_command_catalog
|
||||
@echo ""
|
||||
@echo "=== Running Exec Catalog Tests ==="
|
||||
./test_exec_catalog
|
||||
@echo ""
|
||||
@echo "=== Running Help Text Tests ==="
|
||||
./test_help_text
|
||||
@echo ""
|
||||
|
|
|
|||
49
tests/unit/test_exec_catalog.c
Normal file
49
tests/unit/test_exec_catalog.c
Normal file
|
|
@ -0,0 +1,49 @@
|
|||
/* Unit tests for SSH exec command help catalog */
|
||||
|
||||
#include "../../include/exec_catalog.h"
|
||||
#include "text_assert.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#define TEST(name) static void test_##name()
|
||||
#define RUN_TEST(name) do { \
|
||||
printf("Running %s... ", #name); \
|
||||
test_##name(); \
|
||||
printf("✓\n"); \
|
||||
tests_passed++; \
|
||||
} while(0)
|
||||
|
||||
static int tests_passed = 0;
|
||||
|
||||
TEST(generates_localized_exec_help) {
|
||||
char en[2048] = {0};
|
||||
char zh[2048] = {0};
|
||||
size_t en_pos = 0;
|
||||
size_t zh_pos = 0;
|
||||
|
||||
exec_catalog_append_help(en, sizeof(en), &en_pos, UI_LANG_EN);
|
||||
exec_catalog_append_help(zh, sizeof(zh), &zh_pos, UI_LANG_ZH);
|
||||
|
||||
assert(strstr(en, "TNT exec interface") != NULL);
|
||||
assert(strstr(en, "Commands:") != NULL);
|
||||
assert(strstr(en, "users [--json]") != NULL);
|
||||
assert(strstr(en, "post MESSAGE") != NULL);
|
||||
assert(strstr(en, "support") == NULL);
|
||||
|
||||
assert(strstr(zh, "TNT exec 接口") != NULL);
|
||||
assert(strstr(zh, "命令:") != NULL);
|
||||
assert(strstr(zh, "users [--json]") != NULL);
|
||||
assert(strstr(zh, "post MESSAGE") != NULL);
|
||||
assert(strstr(zh, "support") == NULL);
|
||||
assert_ascii_angle_placeholders(zh);
|
||||
}
|
||||
|
||||
int main(void) {
|
||||
printf("Running exec catalog unit tests...\n\n");
|
||||
|
||||
RUN_TEST(generates_localized_exec_help);
|
||||
|
||||
printf("\n✓ All %d tests passed!\n", tests_passed);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -141,14 +141,6 @@ TEST(text_lookup_matches_language) {
|
|||
"Unknown command") != NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_UNKNOWN_COMMAND_FORMAT),
|
||||
"未知命令") != NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_EXEC_HELP),
|
||||
"TNT exec interface") != NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_EXEC_HELP),
|
||||
"support") == NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_EXEC_HELP),
|
||||
"TNT exec 接口") != NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_EXEC_HELP),
|
||||
"support") == NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_EN, I18N_EXEC_POST_EMPTY),
|
||||
"message cannot be empty") != NULL);
|
||||
assert(strstr(i18n_text(UI_LANG_ZH, I18N_EXEC_POST_EMPTY),
|
||||
|
|
|
|||
Loading…
Reference in a new issue