Files
paulhorn db41258d16 feat: PDA als libpda + pda nach P1204R0
Ersetzt das Geruest (counter/notebook) durch ein echtes Beispiel und teilt
es in zwei eigenstaendige Projekte, wie P1204R0 es fuer Bibliothek plus
Programm verlangt.

libpda: textfile (C, Datei-I/O und Feld-Escaping), calculator
(Recursive-Descent-Parser mit std::expected), contact, editor, explorer.
Exportiert pda::pda ueber install(EXPORT) und ist per find_package(pda)
benutzbar.

pda: Shell ohne Ein-/Ausgabe (execute() gibt Text zurueck, deshalb ohne
Terminal testbar), REPL und Stapelbetrieb in main.cpp.

examples/consumer und tools/check-install.sh pruefen die Export-Kette
Ende-zu-Ende: installieren, dann ein fremdes Projekt dagegen bauen.

docs/CMAKE.md erklaert das Target-Modell, PUBLIC/PRIVATE/INTERFACE,
Generator-Ausdruecke, install/export und Symbolsichtbarkeit an diesem
Projekt.

71 Tests gruen unter Homebrew-clang 22, Apple clang und GCC 16, statisch
und shared, mit und ohne ASan/UBSan.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-08-30 16:39:35 +02:00

3.8 KiB

playground

Ein kleiner PDA — Kontakte, Taschenrechner, Notizen, Dateiexplorer — als Übungsprojekt für die Bau- und Projektstruktur, die dahintersteht.

Aufgeteilt nach P1204R0 „Canonical Project Structure" in zwei eigenständige Projekte:

playground/                    Superprojekt, kein eigener Quellcode
├── libpda/                    die Bibliothek        -> libpda.a
│   ├── libpda/
│   │   ├── textfile.h/.c        C: Datei-I/O und Feld-Escaping
│   │   ├── calculator.hpp/.cpp   Ausdrucksparser (Recursive Descent)
│   │   ├── contact.hpp/.cpp      Kontaktverwaltung mit Persistenz
│   │   ├── editor.hpp/.cpp       zeilenorientierter Textpuffer
│   │   ├── explorer.hpp/.cpp     Verzeichnisnavigation
│   │   ├── *.test.c/.cpp         Unit-Tests, direkt neben dem Modul
│   │   └── details/              Implementation Details
│   └── tests/basics/          Integrationstest, nur öffentliche API
├── pda/                       die Anwendung         -> bin/pda
│   ├── pda/shell.hpp/.cpp       Kommandoverarbeitung, ohne Ein-/Ausgabe
│   ├── pda/main.cpp             REPL und Stapelbetrieb
│   └── tests/session/         Integrationstest einer ganzen Sitzung
├── examples/consumer/         fremdes Projekt, benutzt find_package(pda)
├── cmake/                     ProjectDefaults, Warnings, Sanitizers, Config-Vorlage
├── third_party/               vendortes Unity + doctest, nie editieren
├── tools/check-install.sh     prüft die Export-Kette Ende-zu-Ende
└── docs/                      CMAKE.md, CONVENTIONS.md, ADRs

Warum getrennte Projekte: P1204R0 verlangt es, und der praktische Grund ist, dass die Bibliothek ohne die Anwendung baubar, testbar und installierbar sein muss — sonst ist sie keine Bibliothek, sondern ein Unterverzeichnis.

Bauen

cmake --preset debug
cmake --build --preset debug
ctest --preset debug
./build/debug/bin/pda

Presets: debug, release, asan-ubsan, apple-clang, homebrew-gcc, linux-gcc.

Benutzen

Interaktiv:

$ pda
pda 0.1.0 -- 'help' zeigt die Kommandos, 'quit' beendet.
playground> contact add "Anna Schmidt" 0151 anna@example.org meine Schwester
'Anna Schmidt' angelegt (1 Kontakte)
playground> calc (2+3)*4 - 10/2
15
playground> note add Anna anrufen
Zeile 1 angelegt
playground> contact save kontakte.tsv
1 Kontakte nach kontakte.tsv geschrieben

Im Stapelbetrieb — ein Kommando, dann Ende:

pda calc "2^10"          # 1024
pda contact list

Der Exit-Code ist 1, wenn das Kommando scheitert. Fehler gehen nach stderr.

Als Bibliothek benutzen

cmake -S libpda -B build/lib -DCMAKE_INSTALL_PREFIX=/pfad
cmake --build build/lib && cmake --install build/lib

Dann im eigenen Projekt:

find_package(pda 0.1 REQUIRED)
target_link_libraries(mein_programm PRIVATE pda::pda)
#include <libpda/calculator.hpp>

const auto value = pda::evaluate("(1 + 2) * 3 ^ 2");
if (value) std::println("{}", *value);

Ein vollständiges Beispiel steht in examples/consumer/; tools/check-install.sh baut es gegen eine frisch installierte Bibliothek und ist damit der Test für den Export-Mechanismus.

Dokumentation

  • docs/CMAKE.md — CMake an diesem Projekt erklärt: Target-Modell, PUBLIC/PRIVATE/INTERFACE, Generator-Ausdrücke, install/export, Symbolsichtbarkeit, „wann mache ich was?"
  • docs/CONVENTIONS.md — Stil- und Strukturregeln
  • docs/adr/ — Architekturentscheidungen mit Begründung

Stand

71 Tests (Unity für C, doctest für C++, zwei Integrationstreiber ohne Framework). Grün unter Homebrew-clang 22, Apple clang und GCC 16, jeweils statisch und als Shared Library, mit und ohne ASan/UBSan.