1
0
mirror of https://github.com/rkd77/elinks.git synced 2024-11-04 08:17:17 -05:00

config: Rewrite "set" to "unset" and vice versa.

Also, replace OPT_WATERMARK with OPT_MUST_SAVE, which has the opposite
meaning.

Watermarking of aliases does not yet work correctly in this version.
Neither does the "include" command.
This commit is contained in:
Kalle Olavi Niemitalo 2008-02-03 13:07:43 +02:00 committed by Kalle Olavi Niemitalo
parent 6bd961246a
commit 7cdbc908d8
3 changed files with 89 additions and 53 deletions

View File

@ -192,8 +192,8 @@ skip_to_unquoted_newline_or_comment(struct conf_parsing_pos *pos)
/* Parse a command. Returns error code. */
/* If dynamic string credentials are supplied, we will mirror the command at
* the end of the string; however, we won't load the option value to the tree,
* and we will even write option value from the tree to the output string. We
* will only possibly set OPT_WATERMARK flag to the option (if enabled). */
* and we will even write option value from the tree to the output string.
* We will only possibly clear OPT_MUST_SAVE flag in the option. */
static enum parse_error
parse_set(struct option *opt_tree, struct conf_parsing_state *state,
@ -242,6 +242,24 @@ parse_set(struct option *opt_tree, struct conf_parsing_state *state,
show_parse_error(state, ERROR_OPTION);
skip_option_value(&state->pos);
return ERROR_OPTION;
/* TODO: Distinguish between two scenarios:
* - A newer version of ELinks has saved an
* option that this version does not recognize.
* The option must be preserved. (This works.)
* - The user has added an option, saved
* elinks.conf, restarted ELinks, deleted the
* option, and is now saving elinks.conf again.
* The option should be rewritten to "unset".
* (This does not work yet.)
* In both cases, ELinks has no struct option
* for that name. Possible fixes:
* - If the tree has OPT_AUTOCREATE, then
* assume the user had created that option,
* and rewrite it to "unset". Otherwise,
* keep it.
* - When the user deletes an option, just mark
* it with OPT_DELETED, and keep it in memory
* as long as OPT_TOUCHED is set. */
}
if (!option_types[opt->type].read) {
@ -274,21 +292,24 @@ parse_set(struct option *opt_tree, struct conf_parsing_state *state,
}
} else {
/* rewriting a configuration file */
if (opt->flags & OPT_DELETED)
opt->flags &= ~OPT_WATERMARK;
else
opt->flags |= OPT_WATERMARK;
if (option_types[opt->type].write) {
if (opt->flags & OPT_DELETED) {
/* Replace the "set" command with an
* "unset" command. */
add_to_string(mirror, "unset ");
add_bytes_to_string(mirror, optname_orig,
optname_len);
state->mirrored = state->pos.look;
} else if (option_types[opt->type].write) {
add_bytes_to_string(mirror, state->mirrored,
pos_before_value.look
- state->mirrored);
option_types[opt->type].write(opt, mirror);
state->mirrored = state->pos.look;
}
/* Remember that the option need not be
* written to the end of the file. */
opt->flags &= ~OPT_MUST_SAVE;
}
/* This is not needed since this will be WATERMARK'd when
* saving it. We won't need to save it as touched. */
/* if (!str) opt->flags |= OPT_TOUCHED; */
mem_free(val);
}
@ -303,9 +324,6 @@ parse_unset(struct option *opt_tree, struct conf_parsing_state *state,
size_t optname_len;
unsigned char *optname_copy;
/* XXX: This does not handle the autorewriting well and is mostly a
* quick hack than anything now. --pasky */
skip_white(&state->pos);
if (!*state->pos.look) return show_parse_error(state, ERROR_PARSE);
@ -342,10 +360,23 @@ parse_unset(struct option *opt_tree, struct conf_parsing_state *state,
else mark_option_as_deleted(opt);
} else {
/* rewriting a configuration file */
if (opt->flags & OPT_DELETED)
opt->flags |= OPT_WATERMARK;
else
opt->flags &= ~OPT_WATERMARK;
if (opt->flags & OPT_DELETED) {
/* The "unset" command is already in the file,
* and unlike with "set", there is no value
* to be updated. */
} else if (option_types[opt->type].write) {
/* Replace the "unset" command with a
* "set" command. */
add_to_string(mirror, "set ");
add_bytes_to_string(mirror, optname_orig,
optname_len);
add_to_string(mirror, " = ");
option_types[opt->type].write(opt, mirror);
state->mirrored = state->pos.look;
}
/* Remember that the option need not be
* written to the end of the file. */
opt->flags &= ~OPT_MUST_SAVE;
}
}
@ -718,7 +749,6 @@ load_config(void)
static int indentation = 2;
/* 0 -> none, 1 -> only option full name+type, 2 -> only desc, 3 -> both */
static int comments = 3;
static int touching = 0;
static inline unsigned char *
conf_i18n(unsigned char *s, int i18n)
@ -745,12 +775,6 @@ smart_config_output_fn(struct string *string, struct option *option,
if (option->type == OPT_ALIAS)
return;
/* XXX: OPT_LANGUAGE shouldn't have any bussiness here, but we're just
* weird in that area. */
if (touching && !(option->flags & OPT_TOUCHED)
&& option->type != OPT_LANGUAGE)
return;
switch (action) {
case 0:
if (!(comments & 1)) break;
@ -870,23 +894,18 @@ create_config_string(unsigned char *prefix, unsigned char *name,
if (!init_string(&config)) return NULL;
if (savestyle == 3) {
touching = 1;
savestyle = 1;
} else {
touching = 0;
}
prepare_mustsave_flags(options->value.tree,
savestyle == 1 || savestyle == 2);
/* Scaring. */
if (savestyle == 2
|| (savestyle < 2
&& (load_config_file(prefix, name, options, &config, 0)
|| !config.length))) {
|| load_config_file(prefix, name, options, &config, 0)
|| !config.length) {
/* At first line, and in English, write ELinks version, may be
* of some help in future. Please keep that format for it.
* --Zas */
add_to_string(&config, "## ELinks " VERSION " configuration file\n\n");
assert(savestyle >= 0 && savestyle <= 2);
assert(savestyle >= 0 && savestyle <= 3);
switch (savestyle) {
case 0:
add_to_string(&config, conf_i18n(N_(
@ -896,7 +915,7 @@ create_config_string(unsigned char *prefix, unsigned char *name,
"## and all your formatting, own comments etc will be kept as-is.\n"),
i18n));
break;
case 1:
case 1: case 3:
add_to_string(&config, conf_i18n(N_(
"## This is ELinks configuration file. You can edit it manually,\n"
"## if you wish so; this file is edited by ELinks when you save\n"
@ -953,8 +972,6 @@ create_config_string(unsigned char *prefix, unsigned char *name,
done_string(&tmpstring);
get_me_out:
unmark_options_tree(options->value.tree);
return config.source;
}

View File

@ -737,14 +737,22 @@ register_change_hooks(const struct change_hook_info *change_hooks)
}
void
unmark_options_tree(LIST_OF(struct option) *tree)
prepare_mustsave_flags(LIST_OF(struct option) *tree, int set_all)
{
struct option *option;
foreach (option, *tree) {
option->flags &= ~OPT_WATERMARK;
/* XXX: OPT_LANGUAGE shouldn't have any bussiness
* here, but we're just weird in that area. */
if (set_all
|| (option->flags & (OPT_TOUCHED | OPT_DELETED))
|| option->type == OPT_LANGUAGE)
option->flags |= OPT_MUST_SAVE;
else
option->flags &= ~OPT_MUST_SAVE;
if (option->type == OPT_TREE)
unmark_options_tree(option->value.tree);
prepare_mustsave_flags(option->value.tree, set_all);
}
}
@ -770,7 +778,7 @@ check_nonempty_tree(LIST_OF(struct option) *options)
if (opt->type == OPT_TREE) {
if (check_nonempty_tree(opt->value.tree))
return 1;
} else if (!(opt->flags & OPT_WATERMARK)) {
} else if (opt->flags & OPT_MUST_SAVE) {
return 1;
}
}
@ -791,14 +799,14 @@ smart_config_string(struct string *str, int print_comment, int i18n,
int do_print_comment = 1;
if (option->flags & OPT_HIDDEN ||
option->flags & OPT_WATERMARK ||
option->type == OPT_ALIAS ||
!strcmp(option->name, "_template_"))
continue;
/* Is there anything to be printed anyway? */
if (option->type == OPT_TREE
&& !check_nonempty_tree(option->value.tree))
? !check_nonempty_tree(option->value.tree)
: !(option->flags & OPT_MUST_SAVE))
continue;
/* We won't pop out the description when we're in autocreate

View File

@ -24,15 +24,26 @@ enum option_flags {
* this category when adding an option. The 'template' for the added
* hiearchy piece (category) is stored as "_template_" category. */
OPT_AUTOCREATE = 2,
/* This is used just for marking various options for some very dark,
* nasty and dirty purposes. This watermarking should be kept inside
* some very closed and clearly bounded piece of ELinks module, not
* spreaded along whole ELinks code, and you should clear it everytime
* when sneaking outside of the module (except some trivial common
* utility functions). Basically, you don't want to use this flag
* normally ;). It doesn't affect how the option is handled by common
* option handling functions in any way. */
OPT_WATERMARK = 4,
/* The option has been modified in some way and must be saved
* to elinks.conf. ELinks uses this flag only while it is
* saving the options. When the config.saving_style option
* has value 3, saving works like this:
* - First, ELinks sets OPT_MUST_SAVE in the options that have
* OPT_TOUCHED or OPT_DELETED, and clears it in the rest.
* - ELinks then parses the old configuration file. If it
* contains a "set" or "unset" command for this option,
* ELinks rewrites the command and clears OPT_MUST_SAVE.
* - After ELinks has rewritten the configuration file, it
* appends the options that still have the OPT_MUST_SAVE
* flag.
* Other saving styles are variants of this:
* - 0: ELinks does not append any options to the
* configuration file. So OPT_MUST_SAVE has no effect.
* - 1: ELinks initially sets OPT_MUST_SAVE in all options,
* regardless of OPT_TOUCHED and OPT_DELETED.
* - 2: ELinks initially sets OPT_MUST_SAVE in all options,
* and does not read any configuration files. */
OPT_MUST_SAVE = 4,
/* This is used to mark options modified after the last save. That's
* being useful if you want to save only the options whose value
* changed. */
@ -161,7 +172,7 @@ extern void register_change_hooks(const struct change_hook_info *change_hooks);
extern LIST_OF(struct option) *init_options_tree(void);
extern void unmark_options_tree(LIST_OF(struct option) *);
extern void prepare_mustsave_flags(LIST_OF(struct option) *, int set_all);
extern void untouch_options(LIST_OF(struct option) *);
extern void smart_config_string(struct string *, int, int,