commandline params

This commit is contained in:
csh 2025-07-03 18:51:05 +08:00
parent b0f9055852
commit 07feb1c52c
3 changed files with 208 additions and 90 deletions

View File

@ -1,90 +1,45 @@
#include <iostream> #include <iostream>
#include <exception> #include <exception>
#include <memory> #include <memory>
#include <vector> #include <vector>
#include <spdlog/spdlog.h> #include <spdlog/spdlog.h>
#include <spdlog/sinks/stdout_sinks.h> #include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/basic_file_sink.h> #include <spdlog/sinks/basic_file_sink.h>
#include "./lsp/server.hpp" #include "./lsp/server.hpp"
#include "./utils/args_parser.hpp"
void ParseArgs(int argc, char* argv[])
{ int main(int argc, char* argv[])
std::vector<spdlog::sink_ptr> sinks; {
lsp::utils::ServerConfig config = lsp::utils::ArgsParser::Parse(argc, argv);
bool use_stderr = false;
std::string log_file; if (config.show_help)
spdlog::level::level_enum log_level = spdlog::level::info; {
lsp::utils::ArgsParser::PrintHelp(argv[0]);
for (int i = 1; i < argc; ++i) return 0;
{ }
std::string arg = argv[i];
if (arg == "--log=trace") lsp::utils::ArgsParser::SetupLogger(config);
log_level = spdlog::level::trace;
else if (arg == "--log=debug") try
log_level = spdlog::level::debug; {
else if (arg == "--log=info") spdlog::info("TSL-LSP server starting...");
log_level = spdlog::level::info; lsp::LspServer server(config.thread_count);
else if (arg == "--log=warn") server.Run();
log_level = spdlog::level::warn; }
else if (arg == "--log=error") catch (const std::exception& e)
log_level = spdlog::level::err; {
else if (arg == "--log=off") std::cerr << "[TSL-LSP] Server fatal error: " << e.what() << std::endl;
log_level = spdlog::level::off; spdlog::error("Server fatal error: ", e.what());
else if (arg.find("--log-file=") == 0) return 1;
log_file = arg.substr(11); // 跳过 "--log-file=" }
else if (arg == "--log-stderr") catch (...)
use_stderr = true; {
} std::cerr << "[TSL-LSP] Server unknown fatal error" << std::endl;
spdlog::error("Server unknown fatal error");
sinks.clear(); return 1;
}
if (use_stderr)
sinks.push_back(std::make_shared<spdlog::sinks::stderr_sink_mt>()); spdlog::info("TSL-LSP server stopped normally");
// 如果指定了日志文件,添加文件 sink spdlog::shutdown();
if (!log_file.empty()) return 0;
{ }
try
{
sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(log_file, true));
}
catch (const std::exception& e)
{
std::cerr << "[TSL-LSP] Failed to create log file: " << e.what() << std::endl;
}
}
std::shared_ptr<spdlog::logger> logger = std::make_shared<spdlog::logger>("tsl_lsp", sinks.begin(), sinks.end());
logger->set_level(log_level);
logger->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");
// 设置为默认日志器
spdlog::set_default_logger(logger);
spdlog::flush_on(spdlog::level::warn);
}
int main(int argc, char* argv[])
{
ParseArgs(argc, argv);
try
{
spdlog::info("TSL-LSP server starting...");
lsp::LspServer server;
server.Run();
}
catch (const std::exception& e)
{
std::cerr << "[TSL-LSP] Server fatal error: " << e.what() << std::endl;
spdlog::error("Server fatal error: ", e.what());
return 1;
}
catch (...)
{
std::cerr << "[TSL-LSP] Server unknown fatal error" << std::endl;
spdlog::error("Server unknown fatal error");
return 1;
}
spdlog::info("TSL-LSP server stopped normally");
spdlog::shutdown();
return 0;
}

View File

@ -0,0 +1,140 @@
#include <iostream>
#include <spdlog/sinks/stdout_sinks.h>
#include <spdlog/sinks/basic_file_sink.h>
#include "./args_parser.hpp"
namespace lsp::utils
{
ServerConfig ArgsParser::Parse(int argc, char* argv[])
{
ServerConfig config;
for (int i = 1; i < argc; ++i)
{
std::string arg = argv[i];
if (arg == "--help")
{
config.show_help = true;
return config;
}
if (arg == "--log=trace")
config.log_level = spdlog::level::trace;
else if (arg == "--log=debug")
config.log_level = spdlog::level::debug;
else if (arg == "--log=info")
config.log_level = spdlog::level::info;
else if (arg == "--log=warn")
config.log_level = spdlog::level::warn;
else if (arg == "--log=error")
config.log_level = spdlog::level::err;
else if (arg == "--log=off")
config.log_level = spdlog::level::off;
else if (arg.find("--log-file=") == 0)
config.log_file = arg.substr(11);
else if (arg == "--log-stderr")
config.use_stderr = true;
else if (arg.find("--threads=") == 0)
{
std::string count_str = arg.substr(10);
try
{
size_t count = std::stoul(count_str);
if (count == 0 || count > 32)
{
std::cerr << "[TSL-LSP] Error: Thread count must be between 1 and 32" << std::endl;
std::exit(1);
}
config.thread_count = count;
}
catch (const std::exception&)
{
std::cerr << "[TSL-LSP] Error: Invalid thread count: " << count_str << std::endl;
std::exit(1);
}
}
else
{
std::cerr << "[TSL-LSP] Error: Unknown argument: " << arg << std::endl;
std::cerr << "Use --help for usage information" << std::endl;
}
}
return config;
}
void ArgsParser::SetupLogger(const ServerConfig& config)
{
std::vector<spdlog::sink_ptr> sinks;
if (config.use_stderr)
sinks.push_back(std::make_shared<spdlog::sinks::stderr_sink_mt>());
if (!config.log_file.empty())
{
try
{
sinks.push_back(std::make_shared<spdlog::sinks::basic_file_sink_mt>(config.log_file, true));
}
catch (const std::exception& e)
{
std::cerr << "[TSL-LSP] Failed to create log file: " << e.what() << std::endl;
}
}
auto logger = std::make_shared<spdlog::logger>("tsl_lsp", sinks.begin(), sinks.end());
logger->set_level(config.log_level);
logger->set_pattern("[%Y-%m-%d %H:%M:%S] [%^%l%$] %v");
spdlog::set_default_logger(logger);
spdlog::flush_on(spdlog::level::warn);
}
void ArgsParser::PrintHelp(const std::string& program_name)
{
// 获取硬件线程数
size_t hardware_threads = std::thread::hardware_concurrency();
if (hardware_threads == 0)
hardware_threads = 0; // 表示无法检测
std::cout << "TSL Language Server Protocol (LSP) Server\n"
<< "\n"
<< "Usage: " << program_name << " [options]\n"
<< "\n"
<< "Options:\n"
<< " --help, -h Show this help message and exit\n"
<< "\n"
<< "Logging options:\n"
<< " --log=LEVEL Set log level (trace, debug, info, warn, error, off)\n"
<< " Default: info\n"
<< " --log-file=PATH Write logs to file at PATH\n"
<< " --log-stderr Output logs to stderr\n"
<< "\n"
<< "Performance options:\n"
<< " --threads=N Set number of worker threads (1-32)\n"
<< " Default: 4\n";
// 显示硬件信息
if (hardware_threads > 0)
std::cout << " Hardware threads available: " << hardware_threads << "\n";
else
std::cout << " Hardware threads: unable to detect\n";
std::cout << "\n"
<< "Examples:\n"
<< " # Run with debug logging to stderr\n"
<< " " << program_name << " --log=debug --log-stderr\n"
<< "\n"
<< " # Run with 8 worker threads and log to file\n"
<< " " << program_name << " --threads=8 --log-file=server.log\n"
<< "\n"
<< " # Run with maximum hardware threads\n";
if (hardware_threads > 0)
std::cout << " " << program_name << " --threads=" << hardware_threads << "\n";
else
std::cout << " " << program_name << " --threads=16 # adjust based on your CPU\n";
}
}

View File

@ -0,0 +1,23 @@
#pragma once
#include <string>
#include <spdlog/spdlog.h>
namespace lsp::utils
{
struct ServerConfig
{
bool use_stderr = false;
std::string log_file;
spdlog::level::level_enum log_level = spdlog::level::info;
size_t thread_count = 4;
bool show_help = false;
};
class ArgsParser
{
public:
static ServerConfig Parse(int argc, char* argv[]);
static void SetupLogger(const ServerConfig& config);
static void PrintHelp(const std::string& program_name);
};
}