# iZo iZo is a small C++17 library that exposes common operating-system services through one consistent API on Windows and Linux. ## Features - Native open, save, folder, message, input, and color dialogs - Command-line flags, values, integers, and positional arguments - UTF-8 text, file-list, and RGBA image clipboard access - Native desktop notifications - Standard application, user, temporary, and executable paths - Managed and blocking processes with pipes, timeouts, and output capture - Move-only dynamic library handles with automatic cleanup - Environment variables and basic system information - Monotonic timing and sleeping - Recursive or non-recursive directory watching - Crash callbacks, debugger detection, debug breaks, and debug output - Opening paths and revealing files in the platform file manager - Battery status, sleep inhibition, shutdown, and restart controls Linux dialogs discover `zenity` or `kdialog` at runtime. Linux clipboard access discovers `wl-clipboard` or `xclip`; notifications use `notify-send`; sleep inhibition uses `systemd-inhibit`. No GUI toolkit is linked into applications. `Shutdown` and `Restart` request immediate system power actions and generally require elevated operating-system privileges. ## Build ```sh cmake -S . -B build -DIZO_BUILD_EXAMPLE=ON -DIZO_BUILD_TESTS=ON cmake --build build ctest --test-dir build ``` The unit test suite targets Linux and runs automatically on Gitea Actions using an `ubuntu-latest` runner. To consume an installed copy: ```cmake find_package(iZo CONFIG REQUIRED) target_link_libraries(your_target PRIVATE iZo::izo) ``` ## Usage Include individual feature headers or the complete API: ```cpp #include izo::CommandLine args(argc, argv); if (args.Has("--verbose")) { // Enable verbose logging. } const auto configPath = args.Get("--config"); const int threads = args.GetInt("--threads", 4); izo::ShowNotification("Build complete", "iZo finished compiling"); izo::ClipboardImage image{2, 1, { 255, 0, 0, 255, 0, 0, 255, 255, }}; izo::SetClipboardImage(image); if (izo::PreventSleep()) { // Run a render job, then release the operating-system sleep inhibitor. izo::AllowSleep(); } izo::DialogOptions options; options.title = "Choose an image"; options.filters = {{"Images", {"*.png", "*.jpg"}}}; if (auto selection = izo::OpenFile(options)) { izo::RevealInFileManager(selection.paths.front()); } if (izo::ShowQuestionBox("Delete file?", "This cannot be undone.") == izo::MessageResponse::Yes) { // Delete it. } if (auto name = izo::ShowInputBox({"Profile", "Display name:"})) { // name.value contains the submitted UTF-8 text. } if (auto color = izo::PickColor({"Accent color", {32, 128, 255}})) { // color.color contains the selected RGB channels. } auto config = izo::GetKnownPath(izo::KnownPath::Config); izo::ProcessOptions process; process.executable = "tool"; process.arguments = {"--input", "asset.png"}; process.captureOutput = true; process.timeoutMs = 5000; const auto completed = izo::RunProcess(process); if (completed.exitCode == 0) { // completed.stdoutText contains the tool output. } process.pipeStdin = true; if (auto running = izo::StartProcess(process)) { running.WriteStdin("input"); running.CloseStdin(); running.Wait(); } ``` Resource-owning APIs are move-only and clean themselves up: ```cpp std::string error; auto library = izo::LoadDynamicLibrary("plugin.dll", &error); if (library) { void* entry = library.Symbol("initialize_plugin", &error); } auto watcher = izo::WatchDirectory( {{"assets"}, true}, [](const izo::FileEvent& event) { // Handle added, removed, modified, or renamed files. // Rename events provide the old path in event.previousPath. }, &error); ``` Dialog calls block until dismissed. Directory callbacks run on the watcher's worker thread and must not destroy their own watcher.