From: Pasi Kallinen Date: Sat, 2 Sep 2017 09:04:27 +0000 (+0300) Subject: Add optional config file sections, selected with CHOOSE X-Git-Tag: NetHack-3.6.1_RC01~410 X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=bfad877fbae926e8fc2d476050a3a9c7c0bf2d35;p=nethack Add optional config file sections, selected with CHOOSE Allows the user to define arbitrarily named optional sections in the config file, and select which of those sections are used. For example: OPTIONS=color CHOOSE=char A,char B [char A] OPTIONS=role:arc,race:dwa,align:law,gender:fem [char B] OPTIONS=role:wiz,race:elf,align:cha,gender:mal --- diff --git a/doc/Guidebook.mn b/doc/Guidebook.mn index a2014253c..de4415790 100644 --- a/doc/Guidebook.mn +++ b/doc/Guidebook.mn @@ -2203,6 +2203,12 @@ can be created with any text editor. Any line in the configuration file starting with `#' is treated as a comment. Empty lines are ignored. .pg +Any line beginning with `[' and ending in `]' is considered a section +marker. The text between the square brackets is the section name. +Lines after a section marker belong to that section, and are +ignored unless a CHOOSE -statement was used to select that section. +Section names are case insensitive. +.pg You can use different configuration statements in the file, some of which can be used multiple times. In general, the statements are written in capital letters, followed by an equals sign, followed by @@ -2267,6 +2273,19 @@ Example: .sd \fBBIND=^X:getpos.autodescribe\fP .ed +.lp CHOOSE +Chooses at random one of the comma-separated parameters as an active +section name. Lines in other sections are ignored. +.pg +Example: +.sd +\fBOPTIONS=color\fP +\fBCHOOSE=char A,char B\fP +\fB[char A]\fP +\fBOPTIONS=role:arc,race:dwa,align:law,gender:fem\fP +\fB[char B]\fP +\fBOPTIONS=role:wiz,race:elf,align:cha,gender:mal\fP +.ed .lp MSGTYPE Change the way messages are shown in the top status line. See the ``Configuring Message Types`` section. diff --git a/doc/Guidebook.tex b/doc/Guidebook.tex index 8937072e9..c4a026a22 100644 --- a/doc/Guidebook.tex +++ b/doc/Guidebook.tex @@ -2688,6 +2688,13 @@ can be created with any text editor. Any line in the configuration file starting with `{\tt \#}' is treated as a comment. Empty lines are ignored. +%.pg +Any line beginning with `{\tt [}' and ending in `{\tt ]}' is considered a section +marker. The text between the square brackets is the section name. +Lines after a section marker belong to that section, and are +ignored unless a CHOOSE -statement was used to select that section. +Section names are case insensitive. + %.pg You can use different configuration statements in the file, some of which can be used multiple times. In general, the statements are @@ -2776,6 +2783,24 @@ Example: \end{verbatim} %.ed +%.lp +\item[\bb{CHOOSE}] +Chooses at random one of the comma-separated parameters as an active +section name. Lines in other sections are ignored. + +%.pg +Example: +%.sd +\begin{verbatim} + OPTIONS=color + CHOOSE=char A,char B + [char A] + OPTIONS=role:arc,race:dwa,align:law,gender:fem + [char B] + OPTIONS=role:wiz,race:elf,align:cha,gender:mal +\end{verbatim} +%.ed + %.lp \item[\bb{MSGTYPE}] Change the way messages are shown in the top status line. diff --git a/doc/fixes36.1 b/doc/fixes36.1 index 2a0ea77a1..85c517573 100644 --- a/doc/fixes36.1 +++ b/doc/fixes36.1 @@ -627,6 +627,7 @@ blinded hero or monster who breathes vapor from broken potion of healing, potion: full == always; extra == if not-cursed; plain == if blessed) sysconf definition BONES_POOLS to allow more bones files per level blessed scroll of fire lets you choose explosion location like stinking cloud +optional sections in the config file, selected with CHOOSE Platform- and/or Interface-Specific New Features diff --git a/src/files.c b/src/files.c index 01ad0569f..ef1f00d46 100644 --- a/src/files.c +++ b/src/files.c @@ -198,6 +198,10 @@ STATIC_DCL void FDECL(set_symhandling, (char *, int)); #ifdef NOCWD_ASSUMPTIONS STATIC_DCL void FDECL(adjust_prefix, (char *, int)); #endif +STATIC_DCL void NDECL(free_config_sections); +STATIC_DCL char *FDECL(choose_random_part, (char *, char)); +STATIC_DCL boolean FDECL(is_config_section, (const char *)); +STATIC_DCL boolean FDECL(handle_config_section, (char *)); #ifdef SELF_RECOVER STATIC_DCL boolean FDECL(copy_bytes, (int, int)); #endif @@ -205,6 +209,10 @@ STATIC_DCL boolean FDECL(copy_bytes, (int, int)); STATIC_DCL int FDECL(open_levelfile_exclusively, (const char *, int, int)); #endif + +static char *config_section_chosen = (char *) 0; +static char *config_section_current = (char *) 0; + /* * fname_encode() * @@ -2130,6 +2138,91 @@ int prefixid; } #endif +/* Choose at random one of the sep separated parts from str. Mangles str. */ +STATIC_OVL char * +choose_random_part(str,sep) +char *str; +char sep; +{ + int nsep = 1; + int csep; + int len = 0; + char *begin = str; + + if (!str) + return (char *) 0; + + while (*str) { + if (*str == sep) nsep++; + str++; + } + csep = rn2(nsep); + str = begin; + while ((csep > 0) && *str) { + str++; + if (*str == sep) csep--; + } + if (*str) { + if (*str == sep) str++; + begin = str; + while (*str && *str != sep) { + str++; + len++; + } + *str = '\0'; + if (len) + return begin; + } + return (char *) 0; +} + +STATIC_OVL void +free_config_sections() +{ + if (config_section_chosen) { + free(config_section_chosen); + config_section_chosen = NULL; + } + if (config_section_current) { + free(config_section_current); + config_section_current = NULL; + } +} + +STATIC_OVL boolean +is_config_section(str) +const char *str; +{ + const char *a = rindex(str, ']'); + + return (a && *str == '[' && *(a+1) == '\0' && (int)(a - str) > 0); +} + +STATIC_OVL boolean +handle_config_section(buf) +char *buf; +{ + if (is_config_section(buf)) { + char *send; + if (config_section_current) { + free(config_section_current); + } + config_section_current = dupstr(&buf[1]); + send = rindex(config_section_current, ']'); + *send = '\0'; + debugpline1("set config section: '%s'", config_section_current); + return TRUE; + } + + if (config_section_current) { + if (!config_section_chosen) + return TRUE; + if (strcmp(config_section_current, config_section_chosen)) + return TRUE; + } + return FALSE; +} + #define match_varname(INP, NAM, LEN) match_optname(INP, NAM, LEN, TRUE) int @@ -2156,6 +2249,9 @@ int src; if (!*buf || *buf == '#' || !strcmp(buf, " ")) return 1; + if (src != SET_IN_SYS && handle_config_section(buf)) + return 1; + /* find the '=' or ':' */ bufp = index(buf, '='); altp = index(buf, ':'); @@ -2183,6 +2279,13 @@ int src; ++bufp; /* skip '='; parseoptions() handles spaces */ parseoptions(bufp, TRUE, TRUE); + } else if (match_varname(buf, "CHOOSE", 6)) { + char *section; + if (config_section_chosen) + free(config_section_chosen); + section = choose_random_part(bufp, ','); + if (section) + config_section_chosen = dupstr(section); } else if (match_varname(buf, "AUTOPICKUP_EXCEPTION", 5)) { add_autopickup_exception(bufp); } else if (match_varname(buf, "BINDINGS", 4)) { @@ -2642,6 +2745,7 @@ int src; /* begin detection of duplicate configfile options */ set_duplicate_opt_detection(1); + free_config_sections(); while (fgets(buf, sizeof buf, fp)) { #ifdef notyet @@ -2665,6 +2769,7 @@ OR: Forbid multiline stuff for alternate config sources. } (void) fclose(fp); + free_config_sections(); /* turn off detection of duplicate configfile options */ set_duplicate_opt_detection(0); return rv;