]> granicus.if.org Git - nethack/commitdiff
Add optional config file sections, selected with CHOOSE
authorPasi Kallinen <paxed@alt.org>
Sat, 2 Sep 2017 09:04:27 +0000 (12:04 +0300)
committerPasi Kallinen <paxed@alt.org>
Sat, 2 Sep 2017 09:21:51 +0000 (12:21 +0300)
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

doc/Guidebook.mn
doc/Guidebook.tex
doc/fixes36.1
src/files.c

index a2014253c9ee34b6044d9dbd01137f3b169c0239..de4415790ec5b00e5ec84f0799e15cbd7a96bf23 100644 (file)
@@ -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.
index 8937072e93d6c4a42a1f3c662d4d19cc86671ea6..c4a026a222a9345c764d43485c567de32b7c1070 100644 (file)
@@ -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.
index 2a0ea77a1469efa3192691e7a5ac61b288f92fd2..85c517573974587a33641fa7532f9dbea0d4301b 100644 (file)
@@ -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
index 01ad0569f767311522cc9c3be013ebedf9414bd3..ef1f00d46d21bde89f7f2c750fe4af8dc6753944 100644 (file)
@@ -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;