Implement /theme apply <name> for themes currently in the in-memory
registry. The file-shadowing branch (read a .theme file from
${weechat_config_dir}/themes/ when no built-in matches) is added in
the next commit together with the parser.
Apply algorithm (theme_apply in core-theme.c):
- Look up the theme in the registry; abort with an error if unknown.
- If weechat.look.theme_backup is on and the target name does not
begin with "backup-", write a full snapshot of every themable
option to ${weechat_config_dir}/themes/backup-<timestamp>.theme
via theme_make_backup; abort the apply if the backup cannot be
written, so the user can always undo.
- Iterate the theme's overrides with theme_applying=1 so the
per-option config_change_color skips its gui refresh; for each
entry look up the option, refuse it if missing or non-themable
(warning to core buffer), otherwise call config_file_option_set.
- Perform a single gui_color_init_weechat + gui_window_ask_refresh
at the end.
- Persist the active label in weechat.look.theme and send signal
"theme_applied" with the name as data.
Add the new option weechat.look.theme_backup (boolean, default on)
which controls the backup-or-abort behaviour described above.
Wire the new /theme apply subcommand into core-command.c with the
existing /theme registration; update help text accordingly.
Add the /theme command with two read-only subcommands for now:
- /theme (or /theme list): list registered themes; the active theme
(matching weechat.look.theme) is marked with "->".
- /theme info <name>: show name, description, creation date, WeeChat
version and override count of a theme.
Both subcommands only consider themes present in the in-memory
registry (registered via core/plugins/scripts). User theme files on
disk are not yet handled: the file parser and transient file reads
land in a later commit together with /theme apply.
Add a new string option "weechat.look.theme" holding the name of the
last theme applied via the upcoming /theme command. It is set
automatically by /theme apply and persisted on disk for /theme info to
display after restart; it is NOT re-applied at startup (the user's
saved color values win to avoid clobbering manual post-apply tweaks).
Amend config_change_color so it skips the gui_color_init_weechat ()
and gui_window_ask_refresh (1) calls when theme_applying is set.
/theme apply will set this flag while iterating overrides so the N
individual option changes do not trigger N redundant screen refreshes;
the apply path then performs a single refresh at the end.
Introduce a new module (core-theme.{c,h}) holding the in-memory registry
of built-in themes used by the upcoming /theme command:
- struct t_theme stores name, description, date and weechat version
captured at registration time, plus a hashtable of overrides keyed by
full option name (file.section.option) -> value string.
- theme_register (name, overrides) creates a new theme or merges the
given overrides into an existing one (later calls override duplicate
keys); this is the API plugins and scripts will use to contribute
per-theme color values.
- theme_search and theme_list provide lookup and ordered enumeration.
- theme_init / theme_end are called from weechat_init / weechat_end.
The theme_applying flag is declared here but not yet consumed (it will
gate config_change_color in the next commit to avoid N redundant
window refreshes during /theme apply).
User theme files are not handled by this module: they are read
transiently inside /theme apply (a later commit) and never cached.
Extend the "t:" filter so the special value "themable" matches every
option whose new themable flag is set, regardless of type (color,
string, integer, boolean, enum). This makes the flag interactively
discoverable in the fset buffer and is the natural way to inspect the
surface area that an upcoming /theme command will be allowed to touch.
The themable flag of an option is now mirrored on struct t_fset_option,
exposed via hdata ("themable", integer) and infolist ("themable",
integer), and printed in the log.
Add an "int themable" field on struct t_config_option. The flag is set
automatically for every CONFIG_OPTION_TYPE_COLOR option, and may be set
explicitly on any other type by suffixing the type argument with
"|themable" in the call to config_file_new_option (e.g. "string|themable"
for a string option whose value contains "${color:...}" references).
Opt in the relevant string options in core (buffer_time_format,
day_change_message_*, item_time_format, nick_color_force, prefix_*,
chat_nick_colors, eval_syntax_colors, color palette aliases) and in the
buflist, fset, irc, relay plugins.
The flag is exposed via hdata, infolist, and print_log so scripts and
/debug can read it. This is the foundation for an upcoming /theme
command that will only be allowed to modify themable options.
On modern 32-bit platforms with a 64-bit time_t, the value returned by SvIV can
be 32-bit (its width depends on how Perl was built), whereas time_t is 64-bit.
Read the date with SvNV instead: a double represents all real timestamps
exactly, so the conversion to time_t no longer depends on the size of the Perl
integer type.