meta_package_manager.bar_plugin_renderer module¶
mpm-side renderer that builds SwiftBar/Xbar plugin output.
Lives in its own module rather than in
meta_package_manager.bar_plugin because that module is
intentionally stdlib-only: the
meta_package_manager.bar_plugin.MPMPlugin class is the
script that gets installed as the user’s actual bar plugin and must
stay light on dependencies.
This module is the heavier mpm-side companion that augments the
shippable plugin code with click_extra, boltons, the manager pool, and
the theme system to produce the final rendered output from
mpm outdated --plugin-output.
- meta_package_manager.bar_plugin_renderer.MAX_VERSION_WIDTH = 18¶
Widest a version renders in a menu line, in characters.
A macOS menu cannot scroll sideways, and the menu item is one line tall, so a row wider than the menu loses its tail: SwiftBar leaves the paragraph style at AppKit’s default
.byWordWrapping, which pushes the last whitespace-delimited token onto a second line the item never draws. The target version is that token, so one over-long package blanks the very column the menu exists to show. The cap also spares every other row, since the table aligns on the widest cell in the column.18comes from surveying 1087 version strings: the 578 captured in the bundled[samples]fixtures and the manager docstrings, plus 509 read off a live macOS inventory. The population has two parts with nothing in between. Versions people read run to 17 characters (152.0.7977.82-1.1, a Homebrew cask), and machine identifiers start at 26 (a Julia build triple, a 40-character commit SHA, and Homebrew’s 50-characterversion,revisionpair).18is the smallest cap that elides none of the first group. Linux package managers reach 22 in the fixtures (2.7+git1722+daf2f52-r0, an OpenWrt package), which this renderer never sees: SwiftBar and Xbar are macOS-only.Override it with the
VAR_MAX_VERSION_WIDTHenvironment variable. SeeBarPluginRenderer.max_version_width().
- meta_package_manager.bar_plugin_renderer.VERSION_ELLIPSIS = '…'¶
Marker standing in for the characters
MAX_VERSION_WIDTHdrops.One character wide in a monospace font, so it costs the table a single column where
...would cost three.
- meta_package_manager.bar_plugin_renderer.VERSION_PREFIX_COLOR = 245¶
Xterm-256 palette index coloring the unchanged version prefix in menu lines.
The CLI table keeps
meta_package_manager.version.diff_versions()’s defaultbright_black(SGR90), which terminals remap to their own theme. SwiftBar instead hard-maps SGR90to a fixedNSColor.darkGray, near-invisible on a dark-mode menu, while its 256-color support renders palette index245as a theme-neutral mid-gray (#8a8a8a), legible on both appearances. Xbar strips the ANSI codes it does not render, so the choice is inert there.
- meta_package_manager.bar_plugin_renderer.LIGHT_MENU_OLD_COLOR = 124¶
Palette index for the old-version (red) suffix on a light-appearance menu.
#af0000, a6.5:1contrast ratio on the cream material. SeeBarPluginRenderer.menu_diff_colors()for why the override exists.
- meta_package_manager.bar_plugin_renderer.LIGHT_MENU_NEW_COLOR = 23¶
Palette index for the new-version (green) suffix on a light-appearance menu.
#006600, a6.3:1contrast ratio on the cream material. SeeBarPluginRenderer.menu_diff_colors().
- meta_package_manager.bar_plugin_renderer.DARK_MENU_NEW_COLOR = 46¶
Palette index for the new-version (green) suffix on a dark-appearance menu.
#00ff00, lifting the worst-case contrast from4.0:1(the adaptiveNSColor.systemGreen) to5.8:1over a bright wallpaper showing through the translucent menu. The old-version (red) suffix keepssystemRed: it is already the most readable recognizable red the xterm-256 palette can express (a pure#ff0000scores lower, and brighter options read as orange). SeeBarPluginRenderer.menu_diff_colors().
- meta_package_manager.bar_plugin_renderer.elide_versions(old, new, width)[source]¶
Shorten a version pair to
widthcharacters, keeping the two told apart.The tail goes first, which is where a version keeps the part nobody reads: a commit SHA, a platform triple, Homebrew’s
version,revisionpair. That cut fails on a rebuild differing only in its last characters (2.6.0-2.suse1699.10against its.11), since both sides would come back as the same string with an arrow between them. The shared head is what gives way then, elided around the boundarycommon_prefix_length()reports, so the…lands where the gray prefix hands over to the colored suffix.Which of the two applies is decided for the pair rather than per version. Deciding per version once rendered
5.0.0~beta1-0ubuntu7as….0~beta1-0ubuntu7beside a5.0.2-0ubuntu1~26…that had kept its head, so the column no longer lined up and the leading5.0was dropped from one side only.
- class meta_package_manager.bar_plugin_renderer.BarPluginRenderer[source]¶
Bases:
MPMPluginAll utilities used to render output compatible with both SwiftBar and Xbar plugin dialect.
The minimal code to locate
mpm, then call it and print its output resides in the plugin itself atmeta_package_manager.bar_plugin.MPMPlugin.best_mpm().All other stuff, especially the rendering code, is managed here, to allow for more complex layouts relying on external Python dependencies. This also limits the number of required updates on the plugin itself.
- property group_by_manager: bool[source]¶
Give each manager a section of its own, in place of one flat list.
How that section is drawn is the host’s business, and no two draw it alike: Xbar opens a fly-out sub-menu, SwiftBar folds an accordion into the menu it came from, and the GNOME Shell extension expands inline. So the name says what the grouping is rather than what any one of them makes of it.
Value is sourced from the
VAR_GROUP_BY_MANAGERenvironment variable.
- property fold_sections: bool[source]¶
Render manager sections as inline accordions instead of sub-menus.
SwiftBar
2.1.0renders an item carryingfold=truealongside its---prefixed children as a collapsible section: clicking the header expands it in place rather than opening a sub-menu, without dismissing the menu, and the expanded state survives a refresh (swiftbar/SwiftBar#480).Depends on
group_by_managerfor the children it folds. Xbar has no equivalent and ignores the parameter, so the grouped layout keeps its sub-menus there.
- property own_panel_per_manager: bool[source]¶
Whether each manager’s packages get a panel of their own.
True for Xbar’s grouped layout alone, where a
---prefixed row opens a fly-out sub-menu. SwiftBar folds the same rows into the menu they came from, and the flat layout never left it, so everywhere else every package sits in one continuous column.
- property max_version_width: int[source]¶
How wide a version may render before it is elided, in characters.
Value is sourced from the
VAR_MAX_VERSION_WIDTHenvironment variable, and defaults toMAX_VERSION_WIDTH. A value below2leaves no room for the ellipsis and any content beside it, so it is read as turning the cap off.
Appearance-adaptive version-diff suffix colors for the menu.
SwiftBar maps
meta_package_manager.version.diff_versions()’s default SGR31/32suffixes to the adaptiveNSColor.systemRed/systemGreen, and exports the menu appearance in theOS_APPEARANCEenvironment variable (which propagates to the mpm outdated –plugin-output subprocess). On the translucent “Liquid Glass” menus of recent macOS releases these system colors lose contrast against the material, so override them per appearance:A light menu washes out both suffixes (the green measured
1.9:1), so darken them toLIGHT_MENU_OLD_COLORandLIGHT_MENU_NEW_COLOR.A dark menu over a bright wallpaper dims the green to
4.0:1, so brighten it toDARK_MENU_NEW_COLOR; the red keepssystemRed, already the most readable red the palette allows.
The result is returned as
diff_versionskeyword arguments. When the variable is absent (a consumer like Xbar, which strips these codes anyway) return an empty mapping, keeping the system-color defaults.
- property mpm_cli: tuple[str, ...][source]¶
Absolute
mpminvocation the menu actions are routed through.Re-enters the very interpreter rendering the menu, so a click runs the
mpmthe plugin called and resolves the same configuration file. Derived fromsys.executablerather thansys.argv[0]: the former is always an absolute path to a runnable entry point, while the latter degrades to a console script, a__main__.pyor a bare-cdepending on howmpmwas started. A Nuitka-compiledmpmis its own interpreter, so it is invoked directly instead of through the module.-Pkeeps the directory the action is spawned from out ofsys.path, where-mprepends it. Without it, an action started from a source checkout imports that tree instead of the installed package, and pairs it with the dependencies the installed version pinned. A7.6.1interpreter reading an8.0.0.dev0tree died onfrom click_extra.table import AUTO_WIDTH. The flag needs Python3.11, and the interpreter rendering the menu is the one re-entered, so its own version decides.Note
The candidates
meta_package_manager.bar_plugin.MPMPlugin.search_mpm()produces are deliberately not reused here. The venv ones lead with a bareuv/pipenv/poetrycommand name, while a bar app spawns a menu action with the barelaunchdPATH, where such a name does not resolve.
- static render_cli(cmd_args)[source]¶
Return a formatted CLI compatible with SwiftBar and Xbar plugin format.
I.e. a string with this schema:
shell=cmd_args[0] param1=cmd_args[1] param2=cmd_args[2] ...
- Return type:
- print_cli_item(*args)[source]¶
Print two CLI entries:
one that opens a visible terminal so the user can follow the execution
a second one, reachable by holding the
Optionkey, that runs silently
- Return type:
- print_upgrade_all_item(manager, submenu='')[source]¶
Print the menu entry to upgrade all outdated package of a manager.
- Return type:
- package_rows(manager)[source]¶
One row of cells per outdated package, with the command it runs and the tooltip restoring whatever the version cap elided.
- version_tooltip(old, new, elided)[source]¶
The untruncated version pair, for an item whose cells were elided.
SwiftBar shows a
tooltipon hover, which is where the charactersmax_version_width()dropped stay reachable. Its parser reads a quoted value whole, so the spaces around the arrow are safe. Xbar has no such parameter and would render the text as part of the label, so it gets nothing.- Return type:
- static align_rows(rows)[source]¶
Lay a set of rows out in aligned columns.
The arrow is centered, so it is what the eye follows down the column, and the version on either side of it grows outwards from there.
- align_managers(rows_by_manager)[source]¶
Align every manager’s rows, together or apart.
Together when the managers share one column, which is the flat layout and SwiftBar’s accordion: a table sized per manager lines its own arrows up and leaves them ragged against the section above, which reads as a mistake in a menu the eye scans in one pass.
Apart when each manager gets a panel of its own, since a width taken from the whole pool would pad every short sub-menu out to the longest package name in it.
- render(outdated_data)[source]¶
Wraps the
_render()method above to capture its<stdout>output.Every producer down the
_renderpath (the inheritedppandprint_errorincluded) writes through bareprintcalls, so redirecting<stdout>captures the whole rendering.- Return type:
- add_upgrade_cli(outdated_data)[source]¶
Augment the outdated data from
mpm outdatedsubcommand with upgrade CLI fields for bar plugin consumption.Every menu action is an
mpm_cliinvocation restricted to the manager owning the section (mpm --brew upgrade wget), never that manager’s own native command. Going back throughmpmis what subjects a click to the same policy as the run that rendered the menu: the configuration file found on the system, and with it the release-age cooldown, the manager selection, the sudo policy and the per-manager overrides. A native command escapes all of them, silently upgrading a packagempmitself would have held back.Only the manager selector and the operation are passed, so every other setting is resolved from the user’s configuration at click time.
A manager is offered the action only when it
implements()it, which is the same predicatempmuses to route the subcommand: a manager it would skip gets aNoneCLI and renders as a label-only menu line.
- print(outdated_data)[source]¶
Print the final plugin rendering to
<stdout>.Capturing the output of the plugin and re-printing it will introduce an extra line return, hence the extra call to
rstrip().Colors are forced on
echo’s auto-detection: the bar plugin capturesmpm outdated --plugin-outputthrough a pipe, whereechowould strip every ANSI code and the version-diff colors would never reach SwiftBar or Xbar. TTY detection is meaningless for this dialect, which flags ANSI rendering per line with theansi=true/ansi=falseparameters. An explicit opt-out (--color=never,NO_COLOR) is still honored: only the automatic (None) state is overridden.- Return type: