--- a/src/main.cpp Mon May 19 15:34:30 2025 +0200 +++ b/src/main.cpp Mon May 19 16:05:58 2025 +0200 @@ -48,7 +48,7 @@ " (repeat option to report multiple authors)\n" " -A, --authormap <file> Apply an author mapping file\n" " -d, --depth <num> The search depth (default: 1, max: 255)\n" - " -f, --fragment Output as fragment\n" + " -f, --fragment [indent] Output as fragment\n" " -h, --help Print this help message\n" " -p, --pull Try to pull the repositories\n" " -s, --separate Output a separate heat map for each repository\n" @@ -86,7 +86,8 @@ "\033[1m--separate\033[22m option is specified in which case each repository is displayed with\n" "its own heat map. By using the \033[1m--fragment\033[22m option, the tool only outputs a\n" "single HTML div container without any header or footer that can be embedded in\n" - "your custom web page.\n" + "your custom web page. You can optionally specify an indentation for that\n" + "container (default is 0 and maximum is 12).\n" , stderr); } @@ -100,10 +101,11 @@ errno = 0; unsigned long d = strtoul(str, &endptr, 10); if (*endptr != '\0' || errno == ERANGE) return true; - if (d < max) { + if (d <= max) { *result = d; return false; } else { + errno = ERANGE; return true; } } @@ -114,7 +116,7 @@ print_help(); return 1; } else if (chk_arg(argv[i], "-d", "--depth")) { - if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.depth, 256)) { + if (i + 1 >= argc || parse_unsigned(argv[++i], &settings.depth, 255)) { fputs("missing or invalid depth\n", stderr); return -1; } @@ -134,6 +136,12 @@ settings.update_repos = true; } else if (chk_arg(argv[i], "-f", "--fragment")) { settings.fragment = true; + if (i + 1 < argc && !parse_unsigned(argv[i+1], &settings.fragment_indent, html::max_external_indentation)) { + i++; + } else if (errno == ERANGE) { + fputs("invalid fragment indentation\n", stderr); + return -1; + } } else if (chk_arg(argv[i], "-s", "--separate")) { settings.separate = true; } else if (chk_arg(argv[i], "-A", "--authormap")) { @@ -201,9 +209,19 @@ // scan for repos fm::repositories repos; for (auto &&path: settings.paths) { + if (!fm::repositories::exists(path)) { + fprintf(stderr, "Path '%s' does not exist!\n", path.c_str()); + return EXIT_FAILURE; + } repos.scan(path, settings.depth); } + // check if we found something + if (repos.count() == 0) { + fprintf(stderr, "No repositories found!\n"); + return EXIT_FAILURE; + } + // update repos, if not disabled if (settings.update_repos) { for (auto &&repo : repos.list()) { @@ -262,7 +280,7 @@ } } - html::open(settings.fragment); + html::open(settings.fragment, settings.fragment_indent); for (const auto &[repo, authors] : heatmap.data()) { bool h1_rendered = false; for (const auto &[author, entries] : authors) {