ab5c468ace
canon new lib|exe creates a project following P1204R0 (Canonical Project Structure) with a .canon.toml manifest and a CMakeLists.txt whose managed block is rendered from that manifest. Generators return a plan; the executor checks every operation before writing, so conflicts write nothing and --dry-run writes nothing. Tests: unit tests next to each source file, golden copies of generated projects, and an end-to-end build of both project kinds. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
54 lines
1.8 KiB
C++
54 lines
1.8 KiB
C++
#include <canon/name.hpp>
|
|
|
|
#include <canon/details/testing.hpp>
|
|
|
|
#include <string_view>
|
|
|
|
using namespace canon;
|
|
|
|
int main() {
|
|
if (const auto n = parse_project_name(project_kind::library, "libhello"); CANON_CHECK(n), n) {
|
|
CANON_CHECK_EQ(n->name, "libhello");
|
|
CANON_CHECK_EQ(n->stem, "hello");
|
|
CANON_CHECK_EQ(n->ident, "hello");
|
|
}
|
|
|
|
if (const auto n = parse_project_name(project_kind::library, "libfoo-bar"); CANON_CHECK(n), n) {
|
|
CANON_CHECK_EQ(n->stem, "foo-bar");
|
|
CANON_CHECK_EQ(n->ident, "foo_bar");
|
|
}
|
|
|
|
if (const auto n = parse_project_name(project_kind::executable, "hello2"); CANON_CHECK(n), n) {
|
|
CANON_CHECK_EQ(n->name, "hello2");
|
|
CANON_CHECK_EQ(n->stem, "hello2");
|
|
}
|
|
|
|
{
|
|
const auto n = parse_project_name(project_kind::library, "hello");
|
|
CANON_CHECK(!n);
|
|
CANON_CHECK(n.error().contains("must start with 'lib'"));
|
|
}
|
|
|
|
{
|
|
const auto n = parse_project_name(project_kind::executable, "libhello");
|
|
CANON_CHECK(!n);
|
|
CANON_CHECK(n.error().contains("must not start with 'lib'"));
|
|
}
|
|
|
|
{
|
|
const auto n = parse_project_name(project_kind::library, "libnew");
|
|
CANON_CHECK(!n);
|
|
CANON_CHECK(n.error().contains("C++ keyword"));
|
|
}
|
|
|
|
for (const std::string_view bad : {"lib", "libHello", "lib2d", "libfoo-", "libfoo--bar",
|
|
"libfoo_-bar", "libfoo.bar", "lib-foo", "libfoo bar"}) {
|
|
CANON_CHECK_EQ(parse_project_name(project_kind::library, bad).has_value(), false);
|
|
}
|
|
for (const std::string_view bad : {"", "Hello", "2hello", "hello!", "new", "hello-"}) {
|
|
CANON_CHECK_EQ(parse_project_name(project_kind::executable, bad).has_value(), false);
|
|
}
|
|
|
|
return details::exit_status();
|
|
}
|