feat: the manual is a Mallard set opened in Yelp, not a GResource in the binary
The help was 14 Pango-markup `.txt` bodies in a second GResource, drawn into a paged `GtkWindow` built in `help_window.cpp`. That made F1 a viewer of ours with no search index, no cross-references and no translation, and it kept the manual in the *binary* when every other desktop application's is a document on disk. It is now a real Mallard set: help/C/org.udpscope.app/ index.page + 14 topic pages + figures/*.png and `show_help()` hands `help:org.udpscope.app` to whatever the desktop registered for the `help:` scheme -- Yelp on GNOME -- through a `GtkUriLauncher`, reporting a launch failure with a `GtkAlertDialog` rather than a click that silently does nothing. The paged window's builder, the page table and `help_self_check()`'s markup validation are gone with the resource. The document identifier is the desktop file's own basename (its desktop-file id), derived in CMakeLists from `data/org.udpscope.app.desktop.in`, so the same string is the `.desktop` name, the GApplication id and the install directory at once. The set is installed by a new `install()` rule to `<datadir>/help/C/org.udpscope.app/` -- where the freedesktop Help System Specification's `help:` URI resolves `help:<id>` -- so the manual is read from a datadir by another process even though the binary has no install step. `UDPSCOPE_HELP_NAME` and `UDPSCOPE_HELP_DIR` are compiled in from that one place. The 14 pages were migrated fact for fact, but restructured the Mallard way: a `<desc>` per page (what a search result shows), `<steps>` for procedures, `<terms>` for option lists, `<gui>`/`<key>`/`<keyseq>` for interface words and keys, `<note>` for the asides, and a topic graph via `<link type="guide" xref="index#main"/>`. The figures are annotated screenshots produced by `tools/make-help-shots.sh`, which drives the app headlessly against `tools/mock_udpstreamer.py` and draws the boxes with ImageMagick; the side panel's box is measured from the app's own `side=NNNx` dump reading, the header and status bands come from a documented table, and a crop whose standard deviation is 0 fails the script. `cmake --build build --target test-help` checks the set the way `test-ui` checks the `.ui` files: `yelp-check`'s offline subcommands (links, media, orphans, ids) and a `yelp-build html` render. `yelp-check validate` is deliberately absent -- it fetches the Mallard RelaxNG schema over the network and fails offline for that reason, not for a fault in the pages. The `[help]` probe reading changes with the resource it was written for. `parsed == pages` over in-binary markup cannot exist now, so `help_self_check()` scans `UDPSCOPE_HELP_DIR` and the line reads `topics=14 index=1 figures=3`; `topics=0 index=0` is the manual missing from the tree, which is the finding the old count named. Verified: clean build with the documented three warnings (the help bundle's `-Woverlength-strings` is gone, so the baseline moves from four to three); test-ui 14/14; test-help clean (the four subcommands and 15 pages rendered); a temp-prefix install lands 15 `.page` files and 3 figures at `share/help/C/org.udpscope.app/`; the headless run reads `[help] topics=14 index=1 figures=3 dir=...` with 0 Gtk-CRITICAL. Yelp's own window could not be exercised on this box -- it starts under Xvfb, activates its portals and never maps, the same WebKit/portal limitation that stops a grab -- so its rendering and its search index are unverified here; the content pipeline was (`yelp-build` renders the whole set). Docs: the manual's build/install/open story in `build-and-run.md` and README; the warning baseline in `verification.md`/CLAUDE.md; the help bullets in `invariants-gtk-and-chrome.md`; the `[help]` line in `probe-readings.md`.
This commit is contained in:
1 parent
620473a5be
commit
c1460a6977
47 files changed
+1910
-1056
No files matched your search
+62
-19
@@ -11,6 +11,8 @@ if(NOT CMAKE_BUILD_TYPE AND NOT CMAKE_CONFIGURATION_TYPES)
|
||||
endif()
|
||||
|
||||
find_package(Threads REQUIRED)
|
||||
# `CMAKE_INSTALL_DATADIR` (the `share` under the prefix) for the help set's install path.
|
||||
include(GNUInstallDirs)
|
||||
|
||||
# --- libadwaita: the shortcut overview ---------------------------------------
|
||||
# GTK4's own `GtkShortcutsWindow` is deprecated as of 4.18 and libadwaita's
|
||||
@@ -61,22 +63,35 @@ add_custom_command(
|
||||
COMMENT "Compiling udpscope icon resources"
|
||||
VERBATIM)
|
||||
|
||||
# --- help pages: Pango markup in a GResource ----------------------------------
|
||||
# A second bundle beside the icons'. --c-name is given explicitly so the two generated
|
||||
# sources cannot collide on symbol names.
|
||||
set(UDPSCOPE_HELP_DIR ${CMAKE_CURRENT_SOURCE_DIR}/src/help)
|
||||
file(GLOB UDPSCOPE_HELP_FILES CONFIGURE_DEPENDS ${UDPSCOPE_HELP_DIR}/*.txt)
|
||||
add_custom_command(
|
||||
OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/udpscope_help_resources.c
|
||||
COMMAND ${GLIB_COMPILE_RESOURCES}
|
||||
--target=${CMAKE_CURRENT_BINARY_DIR}/udpscope_help_resources.c
|
||||
--sourcedir=${UDPSCOPE_HELP_DIR}
|
||||
--c-name=udpscope_help
|
||||
--generate-source
|
||||
${UDPSCOPE_HELP_DIR}/udpscope-help.gresource.xml
|
||||
DEPENDS ${UDPSCOPE_HELP_DIR}/udpscope-help.gresource.xml ${UDPSCOPE_HELP_FILES}
|
||||
COMMENT "Compiling udpscope help resources"
|
||||
VERBATIM)
|
||||
# --- the manual: a Mallard help set, installed for the `help:` URI ------------
|
||||
# The manual is no longer a GResource compiled into the binary. It is a Mallard set that the
|
||||
# desktop help viewer (Yelp on GNOME) reads off disk, because that is the only way `F1` can
|
||||
# open a real, searchable, translatable document and the only way the freedesktop Help System
|
||||
# Specification's `help:` URI resolves it. The user documentation is then *files*, checked and
|
||||
# installed rather than compiled in.
|
||||
#
|
||||
# The document identifier -- the `<name>` in `help:<name>` -- is derived from the desktop
|
||||
# file's own basename (its desktop-file id), not written out twice: the same string is the
|
||||
# `.desktop` file, the GApplication id and the installed directory. The specification installs
|
||||
# a document at `<datadir>/help/<lang>/<document>/` and resolves `help:<document>` to the first
|
||||
# match under $XDG_DATA_HOME/$XDG_DATA_DIRS, so the directory name *is* the identifier.
|
||||
# NAME_WE is not used: it strips the *longest* extension, so it would cut `org.udpscope.app`
|
||||
# down to `org`. Strip the two suffixes this one file actually carries, in order.
|
||||
get_filename_component(_udpscope_desktop
|
||||
${CMAKE_CURRENT_SOURCE_DIR}/data/org.udpscope.app.desktop.in NAME)
|
||||
string(REGEX REPLACE "\\.desktop\\.in$" "" UDPSCOPE_HELP_NAME "${_udpscope_desktop}")
|
||||
unset(_udpscope_desktop)
|
||||
set(UDPSCOPE_HELP_SRC ${CMAKE_CURRENT_SOURCE_DIR}/help/C/${UDPSCOPE_HELP_NAME})
|
||||
file(GLOB UDPSCOPE_HELP_FILES CONFIGURE_DEPENDS
|
||||
${UDPSCOPE_HELP_SRC}/*.page ${UDPSCOPE_HELP_SRC}/figures/*.png)
|
||||
|
||||
# The install rule the specification asks for. `CMAKE_INSTALL_DATADIR` is `share` by default,
|
||||
# so the set lands at `<prefix>/share/help/C/<document>/`, which is exactly where a viewer
|
||||
# looks. There is no install step for the binary itself (see the desktop-entry target below),
|
||||
# but the manual is *read from a datadir* by another process, so it has to be installable.
|
||||
install(DIRECTORY ${UDPSCOPE_HELP_SRC}/
|
||||
DESTINATION ${CMAKE_INSTALL_DATADIR}/help/C/${UDPSCOPE_HELP_NAME}
|
||||
FILES_MATCHING PATTERN "*.page" PATTERN "*.png" PATTERN "*.jpg")
|
||||
|
||||
# --- UI files: GtkBuilder XML in a GResource ----------------------------------
|
||||
# The third bundle, for the same reason as the other two: `.ui` files are data, so they are compiled
|
||||
@@ -97,8 +112,9 @@ add_custom_command(
|
||||
VERBATIM)
|
||||
# The generated source carries each file as one C string literal, and a `.ui` is big enough to pass the
|
||||
# 4095-character minimum the standard requires a compiler to support: `-Woverlength-strings` fires on
|
||||
# generated *data*, not on anything anyone wrote. Silenced for this one generated file (the icon and
|
||||
# help bundles are small enough per file never to need it), so the build stays at its four warnings.
|
||||
# generated *data*, not on anything anyone wrote. Silenced for this one generated file (the icon bundle
|
||||
# is small enough per file never to need it), so the build stays at its three warnings. The manual is
|
||||
# no longer compiled in, so the help bundle's own warning is gone with it.
|
||||
set_source_files_properties(${CMAKE_CURRENT_BINARY_DIR}/udpscope_ui_resources.c
|
||||
PROPERTIES COMPILE_OPTIONS "-Wno-overlength-strings")
|
||||
|
||||
@@ -127,6 +143,28 @@ else()
|
||||
message(WARNING "python3 was not found: the test-ui target is not available")
|
||||
endif()
|
||||
|
||||
# --- the manual: an opt-in check, never part of `cmake --build` -----------------
|
||||
# The manual is hand-written Mallard, and `cmake --build` never reads it -- a broken xref or a
|
||||
# missing figure is a page in the viewer with no content or no image, not a build failure.
|
||||
# `tools/check_help.sh` runs yelp-check's four offline subcommands over the set (links, media,
|
||||
# orphans, ids) and renders the whole set to HTML with yelp-build, so the manual is checked the
|
||||
# way the `.ui` files are. `yelp-check validate` is *not* used: it fetches the Mallard RelaxNG
|
||||
# schema over the network, which is not available here and would make the check depend on it.
|
||||
#
|
||||
# No ALL: this runs only when it is named, so `cmake --build build` is unaffected and
|
||||
# yelp-tools is not a build dependency.
|
||||
find_program(UDPSCOPE_YELP_CHECK NAMES yelp-check)
|
||||
find_program(UDPSCOPE_YELP_BUILD NAMES yelp-build)
|
||||
if(UDPSCOPE_YELP_CHECK AND UDPSCOPE_YELP_BUILD)
|
||||
add_custom_target(test-help
|
||||
COMMAND ${CMAKE_CURRENT_SOURCE_DIR}/tools/check_help.sh ${UDPSCOPE_HELP_SRC}
|
||||
DEPENDS ${UDPSCOPE_HELP_FILES} ${CMAKE_CURRENT_SOURCE_DIR}/tools/check_help.sh
|
||||
COMMENT "Checking the Mallard help set with yelp-check and yelp-build"
|
||||
VERBATIM)
|
||||
else()
|
||||
message(WARNING "yelp-check/yelp-build were not found: the test-help target is not available")
|
||||
endif()
|
||||
|
||||
# --- build info: version, commit and timestamp compiled into the binary -------
|
||||
# Written at configure time so add_executable can name the file, and again on every
|
||||
# build so the commit and the timestamp belong to the binary that is running rather
|
||||
@@ -148,7 +186,6 @@ set_source_files_properties(${UDPSCOPE_BUILD_INFO} PROPERTIES GENERATED TRUE)
|
||||
# --- the application ----------------------------------------------------------
|
||||
add_executable(udpscope
|
||||
${CMAKE_CURRENT_BINARY_DIR}/udpscope_resources.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/udpscope_help_resources.c
|
||||
${CMAKE_CURRENT_BINARY_DIR}/udpscope_ui_resources.c
|
||||
${UDPSCOPE_BUILD_INFO}
|
||||
src/main.cpp
|
||||
@@ -187,6 +224,12 @@ add_executable(udpscope
|
||||
)
|
||||
|
||||
target_include_directories(udpscope PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/src)
|
||||
# The manual's identifier (`show_help()` builds `help:<id>` from it) and its directory in the
|
||||
# source tree (what `help_self_check()` scans). Both come from the block near the top, so the
|
||||
# identifier is the desktop file's basename and nothing is written out twice.
|
||||
target_compile_definitions(udpscope PRIVATE
|
||||
UDPSCOPE_HELP_NAME="${UDPSCOPE_HELP_NAME}"
|
||||
UDPSCOPE_HELP_DIR="${UDPSCOPE_HELP_SRC}")
|
||||
target_link_libraries(udpscope PRIVATE plot::gtk4 udpsclient Threads::Threads
|
||||
PkgConfig::ADWAITA)
|
||||
add_dependencies(udpscope udpscope_build_info)
|
||||
|
||||
Reference in new issue
Block a user