mirror of
https://github.com/weechat/weechat.git
synced 2026-06-12 14:14:48 +02:00
core: implement /theme apply with themable enforcement and auto-backup
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.
This commit is contained in:
+19
-1
@@ -7231,6 +7231,13 @@ COMMAND_CALLBACK(theme)
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/* "/theme apply <name>": apply a theme */
|
||||
if (string_strcmp (argv[1], "apply") == 0)
|
||||
{
|
||||
COMMAND_MIN_ARGS(3, "apply");
|
||||
return theme_apply (argv[2]);
|
||||
}
|
||||
|
||||
/* "/theme info <name>": show details about a theme */
|
||||
if (string_strcmp (argv[1], "info") == 0)
|
||||
{
|
||||
@@ -9927,10 +9934,13 @@ command_init (void)
|
||||
N_("manage color themes"),
|
||||
/* TRANSLATORS: only text between angle brackets (eg: "<name>") may be translated */
|
||||
N_("[list]"
|
||||
" || apply <name>"
|
||||
" || info <name>"),
|
||||
CMD_ARGS_DESC(
|
||||
N_("raw[list]: list registered themes (default action with no "
|
||||
"argument); active theme is marked with \"->\""),
|
||||
N_("raw[apply]: apply a theme (set every themable option to the "
|
||||
"value from the theme)"),
|
||||
N_("raw[info]: display details on a theme (name, description, "
|
||||
"creation date, WeeChat version, number of option overrides)"),
|
||||
N_("name: name of a theme"),
|
||||
@@ -9939,8 +9949,16 @@ command_init (void)
|
||||
"option overrides. Built-in themes are registered in memory "
|
||||
"by core/plugins/scripts; user themes are read from files "
|
||||
"in directory \"themes\" inside the WeeChat configuration "
|
||||
"directory.")),
|
||||
"directory."),
|
||||
"",
|
||||
N_("By default, /theme apply creates a backup of current "
|
||||
"themable values in directory \"themes\" before applying "
|
||||
"(file name: \"backup-<timestamp>.theme\"); the previous "
|
||||
"state can be restored with: /theme apply "
|
||||
"backup-<timestamp>. This is controlled by the option "
|
||||
"weechat.look.theme_backup.")),
|
||||
"list"
|
||||
" || apply"
|
||||
" || info",
|
||||
&command_theme, NULL, NULL);
|
||||
hook_command (
|
||||
|
||||
@@ -224,6 +224,7 @@ struct t_config_option *config_look_separator_vertical = NULL;
|
||||
struct t_config_option *config_look_tab_whitespace_char = NULL;
|
||||
struct t_config_option *config_look_tab_width = NULL;
|
||||
struct t_config_option *config_look_theme = NULL;
|
||||
struct t_config_option *config_look_theme_backup = NULL;
|
||||
struct t_config_option *config_look_time_format = NULL;
|
||||
struct t_config_option *config_look_whitespace_char = NULL;
|
||||
struct t_config_option *config_look_window_auto_zoom = NULL;
|
||||
@@ -4433,6 +4434,18 @@ config_weechat_init_options (void)
|
||||
"only, the theme is not re-applied at startup"),
|
||||
NULL, 0, 0, "", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
config_look_theme_backup = config_file_new_option (
|
||||
weechat_config_file, weechat_config_section_look,
|
||||
"theme_backup", "boolean",
|
||||
N_("create a backup theme file with the current themable "
|
||||
"options before applying a theme with command /theme; if "
|
||||
"the backup file cannot be written, the apply is aborted "
|
||||
"(no option is changed); the backup file is written to "
|
||||
"directory \"themes\" inside the WeeChat configuration "
|
||||
"directory and can be restored with: /theme apply "
|
||||
"backup-<timestamp>"),
|
||||
NULL, 0, 0, "on", NULL, 0,
|
||||
NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL);
|
||||
config_look_time_format = config_file_new_option (
|
||||
weechat_config_file, weechat_config_section_look,
|
||||
"time_format", "string",
|
||||
|
||||
@@ -278,6 +278,7 @@ extern struct t_config_option *config_look_separator_vertical;
|
||||
extern struct t_config_option *config_look_tab_whitespace_char;
|
||||
extern struct t_config_option *config_look_tab_width;
|
||||
extern struct t_config_option *config_look_theme;
|
||||
extern struct t_config_option *config_look_theme_backup;
|
||||
extern struct t_config_option *config_look_time_format;
|
||||
extern struct t_config_option *config_look_whitespace_char;
|
||||
extern struct t_config_option *config_look_window_auto_zoom;
|
||||
|
||||
@@ -25,16 +25,25 @@
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/time.h>
|
||||
#include <time.h>
|
||||
|
||||
#include "weechat.h"
|
||||
#include "core-arraylist.h"
|
||||
#include "core-config.h"
|
||||
#include "core-config-file.h"
|
||||
#include "core-dir.h"
|
||||
#include "core-hashtable.h"
|
||||
#include "core-hook.h"
|
||||
#include "core-string.h"
|
||||
#include "core-theme.h"
|
||||
#include "core-version.h"
|
||||
#include "../gui/gui-chat.h"
|
||||
#include "../gui/gui-color.h"
|
||||
#include "../gui/gui-window.h"
|
||||
#include "../plugins/weechat-plugin.h"
|
||||
|
||||
|
||||
@@ -248,6 +257,280 @@ theme_list (void)
|
||||
return list;
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds the on-disk path for a user theme:
|
||||
* "<weechat_config_dir>/themes/<name>.theme".
|
||||
*
|
||||
* Returned string is allocated; caller frees. Returns NULL on error.
|
||||
*/
|
||||
|
||||
char *
|
||||
theme_user_file_path (const char *name)
|
||||
{
|
||||
char *path = NULL;
|
||||
|
||||
if (!name || !name[0])
|
||||
return NULL;
|
||||
string_asprintf (&path, "%s/themes/%s.theme",
|
||||
weechat_config_dir, name);
|
||||
return path;
|
||||
}
|
||||
|
||||
/*
|
||||
* Builds a unique backup theme name "backup-YYYYMMDD-HHMMSS-uuuuuu".
|
||||
*
|
||||
* Returned string is allocated; caller frees. Returns NULL on error.
|
||||
*/
|
||||
|
||||
char *
|
||||
theme_make_backup_name (void)
|
||||
{
|
||||
struct timeval tv;
|
||||
struct tm *local_time;
|
||||
char buf[128];
|
||||
|
||||
if (gettimeofday (&tv, NULL) != 0)
|
||||
return NULL;
|
||||
local_time = localtime (&tv.tv_sec);
|
||||
if (!local_time)
|
||||
return NULL;
|
||||
snprintf (buf, sizeof (buf),
|
||||
"backup-%04d%02d%02d-%02d%02d%02d-%06ld",
|
||||
local_time->tm_year + 1900,
|
||||
local_time->tm_mon + 1,
|
||||
local_time->tm_mday,
|
||||
local_time->tm_hour,
|
||||
local_time->tm_min,
|
||||
local_time->tm_sec,
|
||||
(long)tv.tv_usec);
|
||||
return strdup (buf);
|
||||
}
|
||||
|
||||
/*
|
||||
* Writes a full snapshot of every themable option to a .theme file at
|
||||
* "<weechat_config_dir>/themes/<name>.theme".
|
||||
*
|
||||
* The themes directory is created if missing. The file contains an
|
||||
* [info] section (name, description, date, weechat version) followed by
|
||||
* an [options] section listing every themable option's current value.
|
||||
*
|
||||
* Returns 1 on success, 0 on error.
|
||||
*/
|
||||
|
||||
int
|
||||
theme_write_file_full (const char *name, const char *description)
|
||||
{
|
||||
char *path, *dir, *value, *now;
|
||||
FILE *file;
|
||||
struct t_config_file *ptr_config;
|
||||
struct t_config_section *ptr_section;
|
||||
struct t_config_option *ptr_option;
|
||||
|
||||
if (!name || !name[0])
|
||||
return 0;
|
||||
|
||||
path = NULL;
|
||||
dir = NULL;
|
||||
string_asprintf (&dir, "%s/themes", weechat_config_dir);
|
||||
if (!dir)
|
||||
return 0;
|
||||
dir_mkdir (dir, 0755);
|
||||
free (dir);
|
||||
|
||||
path = theme_user_file_path (name);
|
||||
if (!path)
|
||||
return 0;
|
||||
|
||||
file = fopen (path, "w");
|
||||
free (path);
|
||||
if (!file)
|
||||
return 0;
|
||||
|
||||
now = theme_format_now ();
|
||||
fprintf (file, "[info]\n");
|
||||
fprintf (file, "name = \"%s\"\n", name);
|
||||
fprintf (file, "description = \"%s\"\n",
|
||||
(description) ? description : "");
|
||||
fprintf (file, "date = \"%s\"\n", (now) ? now : "");
|
||||
fprintf (file, "weechat = \"%s\"\n", version_get_version ());
|
||||
fprintf (file, "\n[options]\n");
|
||||
free (now);
|
||||
|
||||
for (ptr_config = config_files; ptr_config;
|
||||
ptr_config = ptr_config->next_config)
|
||||
{
|
||||
for (ptr_section = ptr_config->sections; ptr_section;
|
||||
ptr_section = ptr_section->next_section)
|
||||
{
|
||||
for (ptr_option = ptr_section->options; ptr_option;
|
||||
ptr_option = ptr_option->next_option)
|
||||
{
|
||||
if (!ptr_option->themable)
|
||||
continue;
|
||||
value = config_file_option_value_to_string (
|
||||
ptr_option, 0, 1, 0);
|
||||
fprintf (file, "%s.%s.%s = %s\n",
|
||||
ptr_config->name, ptr_section->name,
|
||||
ptr_option->name,
|
||||
(value) ? value : "\"\"");
|
||||
free (value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fclose (file);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/*
|
||||
* Creates a timestamped backup theme file with the current themable state.
|
||||
*
|
||||
* Returned string is the backup name (caller frees), NULL on failure.
|
||||
*/
|
||||
|
||||
char *
|
||||
theme_make_backup (void)
|
||||
{
|
||||
char *name;
|
||||
|
||||
name = theme_make_backup_name ();
|
||||
if (!name)
|
||||
return NULL;
|
||||
if (!theme_write_file_full (
|
||||
name,
|
||||
_("Automatic backup written before /theme apply")))
|
||||
{
|
||||
free (name);
|
||||
return NULL;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/*
|
||||
* Applies one override entry (callback for hashtable_map during apply).
|
||||
*
|
||||
* Refuses entries pointing to options that do not exist or that are not
|
||||
* themable, logging a warning to the core buffer; the apply itself still
|
||||
* proceeds with the remaining entries.
|
||||
*/
|
||||
|
||||
void
|
||||
theme_apply_set_option_cb (void *data,
|
||||
struct t_hashtable *hashtable,
|
||||
const void *key,
|
||||
const void *value)
|
||||
{
|
||||
struct t_config_option *option = NULL;
|
||||
|
||||
/* make C compiler happy */
|
||||
(void) data;
|
||||
(void) hashtable;
|
||||
|
||||
config_file_search_with_string ((const char *)key,
|
||||
NULL, NULL, &option, NULL);
|
||||
if (!option)
|
||||
{
|
||||
gui_chat_printf (NULL,
|
||||
_("%sTheme: option \"%s\" not found, skipped"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
(const char *)key);
|
||||
return;
|
||||
}
|
||||
if (!option->themable)
|
||||
{
|
||||
gui_chat_printf (
|
||||
NULL,
|
||||
_("%sTheme: option \"%s\" is not themable, skipped"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
(const char *)key);
|
||||
return;
|
||||
}
|
||||
config_file_option_set (option, (const char *)value, 1);
|
||||
}
|
||||
|
||||
/*
|
||||
* Applies a theme registered in memory.
|
||||
*
|
||||
* If weechat.look.theme_backup is on (and the target name does not begin
|
||||
* with "backup-"), a backup file is written first; on backup failure the
|
||||
* apply is aborted before any option is changed.
|
||||
*
|
||||
* Iterates the theme's overrides with theme_applying=1 so the per-option
|
||||
* change callbacks skip their gui refresh; a single refresh is performed
|
||||
* at the end.
|
||||
*
|
||||
* Returns WEECHAT_RC_OK on success, WEECHAT_RC_ERROR if the theme name
|
||||
* is unknown or the backup could not be created.
|
||||
*/
|
||||
|
||||
int
|
||||
theme_apply (const char *name)
|
||||
{
|
||||
struct t_theme *theme;
|
||||
char *backup_name = NULL;
|
||||
|
||||
if (!name || !name[0])
|
||||
return WEECHAT_RC_ERROR;
|
||||
|
||||
theme = theme_search (name);
|
||||
if (!theme)
|
||||
{
|
||||
gui_chat_printf (NULL,
|
||||
_("%sTheme \"%s\" not found"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR],
|
||||
name);
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
|
||||
/* create a backup of current themable state, if enabled */
|
||||
if (CONFIG_BOOLEAN(config_look_theme_backup)
|
||||
&& (strncmp (name, "backup-", 7) != 0))
|
||||
{
|
||||
backup_name = theme_make_backup ();
|
||||
if (!backup_name)
|
||||
{
|
||||
gui_chat_printf (
|
||||
NULL,
|
||||
_("%sUnable to create theme backup; aborting apply "
|
||||
"(disable option weechat.look.theme_backup to force)"),
|
||||
gui_chat_prefix[GUI_CHAT_PREFIX_ERROR]);
|
||||
return WEECHAT_RC_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
/* apply each override; per-option refreshes are suppressed via the
|
||||
theme_applying flag (see config_change_color) */
|
||||
theme_applying = 1;
|
||||
hashtable_map (theme->overrides, &theme_apply_set_option_cb, NULL);
|
||||
theme_applying = 0;
|
||||
|
||||
/* single refresh at the end */
|
||||
if (gui_init_ok)
|
||||
{
|
||||
gui_color_init_weechat ();
|
||||
gui_window_ask_refresh (1);
|
||||
}
|
||||
|
||||
/* persist the active theme label */
|
||||
config_file_option_set (config_look_theme, name, 1);
|
||||
|
||||
/* tell the user about the backup */
|
||||
if (backup_name)
|
||||
{
|
||||
gui_chat_printf (
|
||||
NULL,
|
||||
_("Previous state saved as theme \"%s\"; to restore: "
|
||||
"/theme apply %s"),
|
||||
backup_name, backup_name);
|
||||
free (backup_name);
|
||||
}
|
||||
|
||||
hook_signal_send ("theme_applied",
|
||||
WEECHAT_HOOK_SIGNAL_STRING, (char *)name);
|
||||
|
||||
return WEECHAT_RC_OK;
|
||||
}
|
||||
|
||||
/*
|
||||
* Initializes the theme subsystem.
|
||||
*
|
||||
|
||||
@@ -44,6 +44,8 @@ extern struct t_theme *theme_search (const char *name);
|
||||
extern struct t_theme *theme_register (const char *name,
|
||||
struct t_hashtable *overrides);
|
||||
extern struct t_arraylist *theme_list (void);
|
||||
extern int theme_apply (const char *name);
|
||||
extern char *theme_make_backup (void);
|
||||
|
||||
extern void theme_init (void);
|
||||
extern void theme_end (void);
|
||||
|
||||
@@ -29,15 +29,25 @@
|
||||
extern "C"
|
||||
{
|
||||
#include <ctype.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include "src/core/core-arraylist.h"
|
||||
#include "src/core/core-config.h"
|
||||
#include "src/core/core-config-file.h"
|
||||
#include "src/core/core-hashtable.h"
|
||||
#include "src/core/core-string.h"
|
||||
#include "src/core/core-theme.h"
|
||||
#include "src/core/weechat.h"
|
||||
#include "src/plugins/plugin.h"
|
||||
|
||||
extern char *theme_format_now (void);
|
||||
extern struct t_theme *theme_alloc (const char *name);
|
||||
extern void theme_free (struct t_theme *theme);
|
||||
extern char *theme_user_file_path (const char *name);
|
||||
extern char *theme_make_backup_name (void);
|
||||
extern int theme_write_file_full (const char *name, const char *description);
|
||||
}
|
||||
|
||||
TEST_GROUP(CoreTheme)
|
||||
@@ -261,6 +271,200 @@ TEST(CoreTheme, List)
|
||||
arraylist_free (list);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_user_file_path
|
||||
*/
|
||||
|
||||
TEST(CoreTheme, UserFilePath)
|
||||
{
|
||||
char *path, *expected;
|
||||
|
||||
/* NULL / empty => NULL */
|
||||
POINTERS_EQUAL(NULL, theme_user_file_path (NULL));
|
||||
POINTERS_EQUAL(NULL, theme_user_file_path (""));
|
||||
|
||||
/* "name" => "<weechat_config_dir>/themes/name.theme" */
|
||||
expected = NULL;
|
||||
string_asprintf (&expected, "%s/themes/dark.theme", weechat_config_dir);
|
||||
path = theme_user_file_path ("dark");
|
||||
CHECK(path != NULL);
|
||||
STRCMP_EQUAL(expected, path);
|
||||
free (path);
|
||||
free (expected);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_make_backup_name
|
||||
*/
|
||||
|
||||
TEST(CoreTheme, MakeBackupName)
|
||||
{
|
||||
char *name;
|
||||
int i;
|
||||
|
||||
name = theme_make_backup_name ();
|
||||
CHECK(name != NULL);
|
||||
|
||||
/* format: "backup-YYYYMMDD-HHMMSS-uuuuuu" (29 chars) */
|
||||
LONGS_EQUAL(29, (long)strlen (name));
|
||||
STRNCMP_EQUAL("backup-", name, 7);
|
||||
|
||||
/* 8 digits for date */
|
||||
for (i = 7; i < 15; i++)
|
||||
CHECK(isdigit ((unsigned char)name[i]));
|
||||
CHECK(name[15] == '-');
|
||||
/* 6 digits for time */
|
||||
for (i = 16; i < 22; i++)
|
||||
CHECK(isdigit ((unsigned char)name[i]));
|
||||
CHECK(name[22] == '-');
|
||||
/* 6 digits for microseconds */
|
||||
for (i = 23; i < 29; i++)
|
||||
CHECK(isdigit ((unsigned char)name[i]));
|
||||
|
||||
free (name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_write_file_full
|
||||
*/
|
||||
|
||||
TEST(CoreTheme, WriteFileFull)
|
||||
{
|
||||
char *path, line[8192];
|
||||
FILE *file;
|
||||
int saw_info, saw_name, saw_description, saw_date, saw_weechat;
|
||||
int saw_options_section, saw_an_option;
|
||||
|
||||
/* refuse empty/NULL */
|
||||
LONGS_EQUAL(0, theme_write_file_full (NULL, NULL));
|
||||
LONGS_EQUAL(0, theme_write_file_full ("", NULL));
|
||||
|
||||
/* write a valid file */
|
||||
LONGS_EQUAL(1, theme_write_file_full ("test_wrt", "a description"));
|
||||
|
||||
path = theme_user_file_path ("test_wrt");
|
||||
CHECK(path != NULL);
|
||||
|
||||
file = fopen (path, "r");
|
||||
CHECK(file != NULL);
|
||||
|
||||
saw_info = saw_name = saw_description = saw_date = saw_weechat = 0;
|
||||
saw_options_section = saw_an_option = 0;
|
||||
while (fgets (line, sizeof (line) - 1, file))
|
||||
{
|
||||
if (strncmp (line, "[info]", 6) == 0)
|
||||
saw_info = 1;
|
||||
else if (strncmp (line, "[options]", 9) == 0)
|
||||
saw_options_section = 1;
|
||||
else if (strncmp (line, "name = \"test_wrt\"", 17) == 0)
|
||||
saw_name = 1;
|
||||
else if (strncmp (line, "description = \"a description\"", 29) == 0)
|
||||
saw_description = 1;
|
||||
else if (strncmp (line, "date = \"", 8) == 0)
|
||||
saw_date = 1;
|
||||
else if (strncmp (line, "weechat = \"", 11) == 0)
|
||||
saw_weechat = 1;
|
||||
else if (saw_options_section
|
||||
&& (strchr (line, '=') != NULL)
|
||||
&& (strchr (line, '.') != NULL))
|
||||
saw_an_option = 1;
|
||||
}
|
||||
fclose (file);
|
||||
|
||||
LONGS_EQUAL(1, saw_info);
|
||||
LONGS_EQUAL(1, saw_name);
|
||||
LONGS_EQUAL(1, saw_description);
|
||||
LONGS_EQUAL(1, saw_date);
|
||||
LONGS_EQUAL(1, saw_weechat);
|
||||
LONGS_EQUAL(1, saw_options_section);
|
||||
LONGS_EQUAL(1, saw_an_option);
|
||||
|
||||
unlink (path);
|
||||
free (path);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_make_backup
|
||||
*/
|
||||
|
||||
TEST(CoreTheme, MakeBackup)
|
||||
{
|
||||
char *name, *path;
|
||||
struct stat st;
|
||||
|
||||
name = theme_make_backup ();
|
||||
CHECK(name != NULL);
|
||||
STRNCMP_EQUAL("backup-", name, 7);
|
||||
LONGS_EQUAL(29, (long)strlen (name));
|
||||
|
||||
/* the backup file must exist on disk */
|
||||
path = theme_user_file_path (name);
|
||||
CHECK(path != NULL);
|
||||
LONGS_EQUAL(0, stat (path, &st));
|
||||
CHECK(st.st_size > 0);
|
||||
|
||||
unlink (path);
|
||||
free (path);
|
||||
free (name);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_apply_set_option_cb
|
||||
* theme_apply
|
||||
*/
|
||||
|
||||
TEST(CoreTheme, Apply)
|
||||
{
|
||||
struct t_hashtable *overrides;
|
||||
struct t_config_option *opt_prefix_error;
|
||||
char *saved_prefix_error, *saved_theme_label;
|
||||
int saved_backup;
|
||||
|
||||
/* NULL / empty / missing name => error */
|
||||
LONGS_EQUAL(WEECHAT_RC_ERROR, theme_apply (NULL));
|
||||
LONGS_EQUAL(WEECHAT_RC_ERROR, theme_apply (""));
|
||||
LONGS_EQUAL(WEECHAT_RC_ERROR, theme_apply ("does_not_exist"));
|
||||
|
||||
/* snapshot the option we will mutate + supporting state */
|
||||
opt_prefix_error = NULL;
|
||||
config_file_search_with_string ("weechat.look.prefix_error",
|
||||
NULL, NULL, &opt_prefix_error, NULL);
|
||||
CHECK(opt_prefix_error != NULL);
|
||||
saved_prefix_error = strdup (CONFIG_STRING(opt_prefix_error));
|
||||
saved_theme_label = strdup (CONFIG_STRING(config_look_theme));
|
||||
saved_backup = CONFIG_BOOLEAN(config_look_theme_backup);
|
||||
|
||||
/* disable backup so the test does not touch the filesystem */
|
||||
config_file_option_set (config_look_theme_backup, "off", 1);
|
||||
|
||||
/* register a theme that flips one themable option, then apply */
|
||||
overrides = make_overrides ("weechat.look.prefix_error", "TEST!",
|
||||
NULL, NULL);
|
||||
theme_register ("apply_test", overrides);
|
||||
hashtable_free (overrides);
|
||||
|
||||
LONGS_EQUAL(WEECHAT_RC_OK, theme_apply ("apply_test"));
|
||||
|
||||
/* override took effect */
|
||||
STRCMP_EQUAL("TEST!", CONFIG_STRING(opt_prefix_error));
|
||||
/* active label persisted */
|
||||
STRCMP_EQUAL("apply_test", CONFIG_STRING(config_look_theme));
|
||||
|
||||
/* restore previous state */
|
||||
config_file_option_set (opt_prefix_error, saved_prefix_error, 1);
|
||||
config_file_option_set (config_look_theme, saved_theme_label, 1);
|
||||
config_file_option_set (config_look_theme_backup,
|
||||
(saved_backup) ? "on" : "off", 1);
|
||||
|
||||
free (saved_prefix_error);
|
||||
free (saved_theme_label);
|
||||
}
|
||||
|
||||
/*
|
||||
* Test functions:
|
||||
* theme_init
|
||||
|
||||
Reference in New Issue
Block a user