#include #include #include #include "./args_parser.hpp" namespace lsp::utils { ArgsParser& ArgsParser::Instance() { static ArgsParser instance; return instance; } const ServerConfig& ArgsParser::Parse(int argc, char* argv[]) { config_ = ServerConfig {}; bool use_stdio = false; 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("--interpreter=") == 0) config_.interpreter_path = arg.substr(14); 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 if (arg == "--stdio") { use_stdio = true; } else { std::cerr << "[TSL-LSP] Error: Unknown argument: " << arg << std::endl; std::cerr << "Use --help for usage information" << std::endl; } } std::cerr << "TSL Language Server " << __DATE__ << std::endl; if (use_stdio) std::cerr << "[TSL-LSP] JosnRPc using stdio" << std::endl; // config_.interpreter_path = "/mnt/c/Programs/Tinysoft/TSLGen2/"; return config_; } const ServerConfig& ArgsParser::GetConfig() const { return config_; } void ArgsParser::SetupLogger(const ServerConfig& config) { std::vector sinks; if (config.use_stderr) sinks.push_back(std::make_shared()); if (!config.log_file.empty()) { try { sinks.push_back(std::make_shared(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("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" << "Version: " << __DATE__ << " build\n" << "\n" << "Usage: " << program_name << " [options]\n" << "\n" << "Options:\n" << " --help Show this help message and exit\n" << "\n" << "Interpreter options:\n" << " --interpreter=PATH Set path to TSL interpreter executable\n" << " Required for some language features\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"; } }