文件
ParlzPackageManger/src/out.c
T
JGZYES 51a88a4678 feature: pmm upgrade + pmm info enhancement + color/quiet/verbose flags
- pmm upgrade [--yes]: scan ~/.pmm/installed/*.info, look up each package's
  latest registry version for this os/arch, and upgrade with a per-package
  prompt (or automatically with --yes). Adds cmp_version + installed_version
  helpers and wires the 'upgrade' subcommand.
- pmm info: also print package description (when present) and an indented
  versions list (or url/sha256 for legacy single-platform entries).
- Output flags: --no-color (also PMM_NO_COLOR=1), -q/--quiet (only warn+error),
  --verbose. Added pmm_no_color + pmm_log_level globals to out.c/out.h and a
  consume_global_flags() pre-dispatch pass in main.c so every subcommand honors
  them. info/success are suppressed only in quiet mode (verbose keeps them).
- help: document upgrade, --no-color, -q/--quiet, --verbose.

Verified on WSL gcc: compiles clean; no-color strips ANSI on tty, -q silences
info/success while keeping errors, --verbose keeps info, info lists description
+ versions, upgrade recognizes up-to-date packages.
2026-09-04 20:13:42 +08:00

66 行
2.3 KiB
C

/* out.c - colored/structured console output implementation */
#include "out.h"
#include <stdio.h>
#include <stdarg.h>
#include <string.h>
#ifdef _WIN32
#include <io.h>
#define IS_TTY_FD(fd) _isatty(fd)
#else
#include <unistd.h>
#define IS_TTY_FD(fd) isatty(fd)
#endif
/* Global output flags (extern in out.h). Set from main.c flags / env. */
int pmm_no_color = 0; /* --no-color / PMM_NO_COLOR=1: never emit ANSI */
int pmm_log_level = 0; /* 0 normal, 1 quiet (-q), 2 verbose (--verbose) */
/* Emit a message with an optional ANSI colour and a [PMM]:[LEVEL] prefix.
* fd_stream: 1 for stdout (info/success), 2 for stderr (error/warn).
* colour is the ANSI SGR number (0 = no colour), OR "" style. We always write
* the plain "[PMM]:[LEVEL]" prefix; colour only wraps it when the tty test
* passes. */
static void pmmsg(FILE *stream, int fd, const char *level, int wrap_color, const char *fmt, va_list ap) {
char buf[4096];
vsnprintf(buf, sizeof(buf), fmt, ap);
/* Trim any trailing newline(s) from the formatted message — many source
* calls end their format with "\n", and we add exactly one below. Without
* this, "[PMM]:[INFO]msg\n" would print a blank line after every message. */
size_t len = strlen(buf);
while (len && (buf[len-1] == '\n' || buf[len-1] == '\r')) buf[--len] = '\0';
int tty = IS_TTY_FD(fd) && !pmm_no_color;
if (tty && wrap_color)
fprintf(stream, "\033[%dm[PMM]:[%s]%s\033[0m\n", wrap_color, level, buf);
else
fprintf(stream, "[PMM]:[%s]%s\n", level, buf);
}
void pmm_error(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
pmmsg(stderr, 2, "ERROR", 31, fmt, ap); /* red */
va_end(ap);
}
void pmm_success(const char *fmt, ...) {
if (pmm_log_level == 1) return; /* quiet: suppress success; verbose(2) keeps it */
va_list ap; va_start(ap, fmt);
pmmsg(stdout, 1, "SUCCESS", 32, fmt, ap); /* green */
va_end(ap);
}
void pmm_info(const char *fmt, ...) {
if (pmm_log_level == 1) return; /* quiet: suppress info; verbose(2) keeps it */
va_list ap; va_start(ap, fmt);
pmmsg(stdout, 1, "INFO", 2, fmt, ap); /* grey (SGR 2 = dim) */
va_end(ap);
}
void pmm_warn(const char *fmt, ...) {
va_list ap; va_start(ap, fmt);
pmmsg(stderr, 2, "WARN", 33, fmt, ap); /* yellow */
va_end(ap);
}