diff options
| author | Dan Engelbrecht <[email protected]> | 2026-04-20 15:53:22 +0200 |
|---|---|---|
| committer | GitHub Enterprise <[email protected]> | 2026-04-20 15:53:22 +0200 |
| commit | 28a61b12d302e9e0d37d52bf1aa5d19069f3411b (patch) | |
| tree | 07cd367f4933364781ea69c350025b1b6b703174 /src/zencore/process.cpp | |
| parent | zen-test: add CLI integration harness + TestArtifactProvider + CI host stats ... (diff) | |
| download | archived-zen-28a61b12d302e9e0d37d52bf1aa5d19069f3411b.tar.xz archived-zen-28a61b12d302e9e0d37d52bf1aa5d19069f3411b.zip | |
zen history command (#987)
- Feature: Per-user invocation history for `zen` and `zenserver`; each startup appends a record to a JSONL file capped at the most recent 100 entries. Location: `%LOCALAPPDATA%\Epic\Zen\History\invocations.jsonl` on Windows, `~/.zen/History/invocations.jsonl` on POSIX
- `zen history` opens an interactive picker; selecting a zen row re-runs it inline and forwards the exit code, selecting a zenserver row spawns it detached
- `zen history --list` (`-l`) prints the table to stdout instead of showing the picker
- `zen history --filter zen|zenserver` restricts the listing to one executable
- `zen history --print` prints the reconstructed command line of the selected row instead of launching it
- `--enable-execution-history` global option on both binaries (default `true`) to opt out per invocation
- The history file is attached to Sentry crash reports (alongside the existing zenserver log)
Diffstat (limited to 'src/zencore/process.cpp')
| -rw-r--r-- | src/zencore/process.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/zencore/process.cpp b/src/zencore/process.cpp index 4708f15cf..5d37c3715 100644 --- a/src/zencore/process.cpp +++ b/src/zencore/process.cpp @@ -906,6 +906,56 @@ BuildArgV(std::vector<char*>& Out, char* CommandLine) #endif // !WINDOWS || TESTS +std::string +GetRawCommandLine() +{ +#if ZEN_PLATFORM_WINDOWS + LPWSTR Raw = ::GetCommandLineW(); + if (Raw == nullptr) + { + return {}; + } + return WideToUtf8(Raw); +#else + return {}; +#endif +} + +std::string +BuildCommandLine(std::span<const std::string> Argv) +{ + constexpr AsciiSet QuoteChars = " \t\""; + + std::string Result; + for (size_t I = 0; I < Argv.size(); ++I) + { + if (I > 0) + { + Result += ' '; + } + + const std::string& Arg = Argv[I]; + const bool NeedsQuotes = Arg.empty() || AsciiSet::HasAny(Arg.c_str(), QuoteChars); + if (!NeedsQuotes) + { + Result += Arg; + continue; + } + + Result += '"'; + for (char Ch : Arg) + { + if (Ch == '"') + { + Result += '\\'; + } + Result += Ch; + } + Result += '"'; + } + return Result; +} + #if ZEN_PLATFORM_WINDOWS static CreateProcResult CreateProcNormal(const std::filesystem::path& Executable, std::string_view CommandLine, const CreateProcOptions& Options) |