fe39de8b22
- CMakeLists.txt template: adds target_link_libraries fn_table_viz with if(TARGET fn_table_viz) guard (compiles even without vendor/lua). - main.cpp template: adds commented include + data_table::render() panel block in render(). Also fixes include to use app_base.h + panel_menu.h (matching convention of chart_demo, shaders_lab). - app.md template: uses_functions lists all 12 fn_table_viz stack IDs commented out; uncomment when activating data_table::render(). - Bump version 0.1.0 -> 1.1.0. Add capability growth log entry. - Tag cpp-tables added to capability group. - Verified: test app test_scaffolder_default compiled clean, residues removed (dir + CMakeLists entry). Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
238 lines
7.0 KiB
Bash
Executable File
238 lines
7.0 KiB
Bash
Executable File
#!/usr/bin/env bash
|
|
# init_cpp_app — Scaffolder estandar de apps C++ del registry.
|
|
#
|
|
# Genera la estructura canonica (main.cpp, CMakeLists.txt, app.md), registra
|
|
# la app en cpp/CMakeLists.txt, inicializa git + repo Gitea dataforge/<name>,
|
|
# y ejecuta fn index. La plantilla cumple cpp/PATTERNS.md y .claude/rules/cpp_apps.md.
|
|
#
|
|
# Uso:
|
|
# init_cpp_app <name> [--project <p>] [--domain <d>] [--desc "..."] [--tags "a,b"]
|
|
#
|
|
# Por defecto domain=tools, sin proyecto (cpp/apps/<name>/).
|
|
|
|
set -euo pipefail
|
|
|
|
# Carga helpers del registry
|
|
FN_ROOT="${FN_REGISTRY_ROOT:-$(git rev-parse --show-toplevel 2>/dev/null || pwd)}"
|
|
# shellcheck source=/dev/null
|
|
source "$FN_ROOT/bash/functions/infra/ensure_repo_synced.sh"
|
|
|
|
init_cpp_app() {
|
|
local name=""
|
|
local project=""
|
|
local domain="tools"
|
|
local desc=""
|
|
local tags=""
|
|
|
|
while [[ $# -gt 0 ]]; do
|
|
case "$1" in
|
|
--project) project="$2"; shift 2 ;;
|
|
--domain) domain="$2"; shift 2 ;;
|
|
--desc) desc="$2"; shift 2 ;;
|
|
--tags) tags="$2"; shift 2 ;;
|
|
-*) echo "init_cpp_app: flag desconocido: $1" >&2; return 2 ;;
|
|
*) if [[ -z "$name" ]]; then name="$1"; else
|
|
echo "init_cpp_app: argumento extra: $1" >&2; return 2
|
|
fi
|
|
shift ;;
|
|
esac
|
|
done
|
|
|
|
if [[ -z "$name" ]]; then
|
|
echo "init_cpp_app: se requiere <name>" >&2
|
|
echo "Uso: init_cpp_app <name> [--project <p>] [--domain <d>] [--desc \"...\"] [--tags \"a,b\"]" >&2
|
|
return 2
|
|
fi
|
|
|
|
[[ -z "$desc" ]] && desc="App C++ del registry"
|
|
|
|
# Resolver dir destino
|
|
local rel_dir abs_dir
|
|
if [[ -n "$project" ]]; then
|
|
if [[ ! -f "$FN_ROOT/projects/$project/project.md" ]]; then
|
|
echo "init_cpp_app: proyecto '$project' no existe (falta projects/$project/project.md)" >&2
|
|
return 1
|
|
fi
|
|
rel_dir="projects/$project/apps/$name"
|
|
else
|
|
rel_dir="cpp/apps/$name"
|
|
fi
|
|
abs_dir="$FN_ROOT/$rel_dir"
|
|
|
|
if [[ -e "$abs_dir" ]]; then
|
|
echo "init_cpp_app: $rel_dir ya existe" >&2
|
|
return 1
|
|
fi
|
|
|
|
mkdir -p "$abs_dir"
|
|
|
|
# ---------- main.cpp ----------
|
|
cat > "$abs_dir/main.cpp" <<EOF
|
|
#include <imgui.h>
|
|
#include "app_base.h"
|
|
#include "core/panel_menu.h"
|
|
#include "core/icons_tabler.h"
|
|
#include "core/logger.h"
|
|
// #include "viz/data_table.h" // uncomment to enable data_table::render() panel
|
|
|
|
// Toggles de paneles (visibles desde el menu View del menubar canonico)
|
|
static bool g_show_main = true;
|
|
|
|
static void draw_main() {
|
|
if (!ImGui::Begin(TI_HOME " Main", &g_show_main)) {
|
|
ImGui::End();
|
|
return;
|
|
}
|
|
ImGui::TextUnformatted("Hello from $name");
|
|
ImGui::End();
|
|
}
|
|
|
|
static void render() {
|
|
// El framework dibuja menubar (View/Layouts/Settings/About) y un
|
|
// DockSpaceOverViewport central (auto_dockspace=true por defecto).
|
|
// Aqui solo se dibujan los paneles propios de la app.
|
|
if (g_show_main) draw_main();
|
|
|
|
// === Data panel (uncomment to enable) ===
|
|
// static data_table::State data_state;
|
|
// static std::vector<data_table::TableInput> data_tables; // populate from your source
|
|
// data_table::render("main_data", data_tables, data_state);
|
|
}
|
|
|
|
int main(int /*argc*/, char** /*argv*/) {
|
|
static fn_ui::PanelToggle panels[] = {
|
|
{ "Main", nullptr, &g_show_main },
|
|
};
|
|
|
|
fn::AppConfig cfg;
|
|
cfg.title = "$name — $desc";
|
|
cfg.about = { "$name", "0.1.0", "$desc" };
|
|
cfg.log = { "$name.log", 1 };
|
|
cfg.panels = panels;
|
|
cfg.panel_count = sizeof(panels) / sizeof(panels[0]);
|
|
|
|
return fn::run_app(cfg, render);
|
|
}
|
|
EOF
|
|
|
|
# ---------- CMakeLists.txt ----------
|
|
cat > "$abs_dir/CMakeLists.txt" <<EOF
|
|
add_imgui_app($name
|
|
main.cpp
|
|
)
|
|
target_include_directories($name PRIVATE \${CMAKE_CURRENT_SOURCE_DIR})
|
|
|
|
# fn_table_viz: provides data_table::render(), viz_render, TQL engine, Lua, LLM.
|
|
# Guard keeps the app compilable in builds where vendor/lua is absent.
|
|
if(TARGET fn_table_viz)
|
|
target_link_libraries($name PRIVATE fn_table_viz)
|
|
endif()
|
|
|
|
if(WIN32)
|
|
set_target_properties($name PROPERTIES WIN32_EXECUTABLE TRUE)
|
|
endif()
|
|
EOF
|
|
|
|
# ---------- app.md ----------
|
|
local repo_url="https://gitea.organic-machine.com/dataforge/$name"
|
|
local tags_yaml="[imgui]"
|
|
if [[ -n "$tags" ]]; then
|
|
# Convierte "a,b,c" -> "[a, b, c]"
|
|
tags_yaml="[$(echo "$tags" | sed 's/,/, /g'), imgui]"
|
|
fi
|
|
|
|
cat > "$abs_dir/app.md" <<EOF
|
|
---
|
|
name: $name
|
|
lang: cpp
|
|
domain: $domain
|
|
description: "$desc"
|
|
tags: $tags_yaml
|
|
uses_functions:
|
|
# Uncomment when using data_table::render() — provided via fn_table_viz:
|
|
# - data_table_cpp_viz
|
|
# - viz_render_cpp_viz
|
|
# - compute_stage_cpp_core
|
|
# - compute_pipeline_cpp_core
|
|
# - compute_column_stats_cpp_core
|
|
# - auto_detect_type_cpp_core
|
|
# - tql_emit_cpp_core
|
|
# - tql_apply_cpp_core
|
|
# - lua_engine_cpp_core
|
|
# - join_tables_cpp_core
|
|
# - tql_to_sql_cpp_core
|
|
# - llm_anthropic_cpp_core
|
|
uses_types: []
|
|
framework: "imgui"
|
|
entry_point: "main.cpp"
|
|
dir_path: "$rel_dir"
|
|
repo_url: "$repo_url"
|
|
---
|
|
|
|
# $name
|
|
|
|
$desc
|
|
|
|
## Build
|
|
|
|
\`\`\`bash
|
|
cd cpp && cmake --build build --target $name -j
|
|
\`\`\`
|
|
|
|
## Run
|
|
|
|
\`\`\`bash
|
|
./cpp/build/$name
|
|
\`\`\`
|
|
EOF
|
|
|
|
# ---------- Registrar en cpp/CMakeLists.txt ----------
|
|
local cpp_cmake="$FN_ROOT/cpp/CMakeLists.txt"
|
|
if ! grep -q "# --- $name ---" "$cpp_cmake"; then
|
|
if [[ -n "$project" ]]; then
|
|
local upper
|
|
upper="$(echo "$name" | tr '[:lower:]' '[:upper:]')"
|
|
cat >> "$cpp_cmake" <<EOF
|
|
|
|
# --- $name (lives in projects/$project/apps/) ---
|
|
set(_${upper}_DIR \${CMAKE_SOURCE_DIR}/../projects/$project/apps/$name)
|
|
if(EXISTS \${_${upper}_DIR}/CMakeLists.txt)
|
|
add_subdirectory(\${_${upper}_DIR} \${CMAKE_BINARY_DIR}/apps/$name)
|
|
endif()
|
|
EOF
|
|
else
|
|
cat >> "$cpp_cmake" <<EOF
|
|
|
|
# --- $name ---
|
|
if(EXISTS \${CMAKE_CURRENT_SOURCE_DIR}/apps/$name/CMakeLists.txt)
|
|
add_subdirectory(apps/$name)
|
|
endif()
|
|
EOF
|
|
fi
|
|
fi
|
|
|
|
# ---------- Git + Gitea ----------
|
|
if [[ -n "${GITEA_URL:-}" && -n "${GITEA_TOKEN:-}" ]]; then
|
|
ensure_repo_synced "$abs_dir" "dataforge" "$name" "master" "feat: scaffold $name via init_cpp_app" || \
|
|
echo "init_cpp_app: warning — ensure_repo_synced fallo, repo no creado" >&2
|
|
else
|
|
echo "init_cpp_app: GITEA_URL/GITEA_TOKEN no seteados, omitiendo creacion de repo Gitea" >&2
|
|
(cd "$abs_dir" && git init -b master >/dev/null 2>&1 || git init >/dev/null 2>&1)
|
|
fi
|
|
|
|
# ---------- fn index ----------
|
|
if [[ -x "$FN_ROOT/fn" ]]; then
|
|
(cd "$FN_ROOT" && ./fn index >/dev/null 2>&1) || \
|
|
echo "init_cpp_app: warning — fn index fallo" >&2
|
|
fi
|
|
|
|
echo "init_cpp_app: $rel_dir creada"
|
|
echo " - Build: cd $FN_ROOT/cpp && cmake --build build --target $name -j"
|
|
echo " - app.md: $rel_dir/app.md (rellena uses_functions cuando uses funciones del registry)"
|
|
}
|
|
|
|
# Permitir invocacion directa via 'fn run init_cpp_app ...'
|
|
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
|
|
init_cpp_app "$@"
|
|
fi
|