From f863b6025897457e1b61d043833e25a35a4c246e Mon Sep 17 00:00:00 2001 From: John Darrington Date: Sun, 13 May 2012 22:25:39 +0200 Subject: [PATCH] Add SET TVARS option. Closes bug #31566 --- doc/utilities.texi | 12 ++- src/data/settings.c | 7 ++ src/data/settings.h | 2 +- src/data/variable.c | 59 ++++++++++++--- src/language/utilities/set.q | 30 ++++++++ tests/language/dictionary/variable-display.at | 74 +++++++++++++++++++ 6 files changed, 172 insertions(+), 12 deletions(-) diff --git a/doc/utilities.texi b/doc/utilities.texi index c568acec6c..b20fa24c85 100644 --- a/doc/utilities.texi +++ b/doc/utilities.texi @@ -423,6 +423,7 @@ SET /MORE=@{ON,OFF@} /WIDTH=@{NARROW,WIDTH,@var{n_characters}@} /TNUMBERS=@{VALUES,LABELS,BOTH@} + /TVARS=@{NAMES,LABELS,BOTH@} (logging) /JOURNAL=@{ON,OFF@} ['@var{file_name}'] @@ -719,7 +720,16 @@ If @subcmd{TNUMBERS} is set to @subcmd{LABELS}, then values are displayed using (@xref{VALUE LABELS}.) If the a value has no label, then it will be displayed using its literal value. If @subcmd{TNUMBERS} is set to @subcmd{BOTH}, then values will be displayed with both their label -(if any) and their literal value in parenthesis. +(if any) and their literal value in parentheses. +@itemx TVARS +The @subcmd{TVARS} option sets the way in which variables are displayed in output tables. +The valid settings are @subcmd{NAMES}, @subcmd{LABELS} and @subcmd{BOTH}. +If @subcmd{TVARS} is set to @subcmd{NAMES}, then all variables are displayed using their names. +If @subcmd{TVARS} is set to @subcmd{LABELS}, then variables are displayed using their label if one +has been set. If no label has been set, then the name will be used. +(@xref{VARIABLE LABELS}.) +If @subcmd{TVARS} is set to @subcmd{BOTH}, then variables will be displayed with both their label +(if any) and their name in parentheses. @end table @cindex headers diff --git a/src/data/settings.c b/src/data/settings.c index 95fda576da..47b3f3d5ce 100644 --- a/src/data/settings.c +++ b/src/data/settings.c @@ -713,3 +713,10 @@ settings_get_var_style (void) { return the_settings.var_output_style; } + + +void +settings_set_var_style (enum settings_var_style s) +{ + the_settings.var_output_style = s; +} diff --git a/src/data/settings.h b/src/data/settings.h index 559f64ebb6..409b7fe9eb 100644 --- a/src/data/settings.h +++ b/src/data/settings.h @@ -121,7 +121,7 @@ enum settings_value_style settings_get_value_style (void); enum settings_var_style settings_get_var_style (void); void settings_set_value_style (enum settings_value_style s); -void settings_set_var_style (enum settings_value_style s); +void settings_set_var_style (enum settings_var_style s); enum behavior_mode { diff --git a/src/data/variable.c b/src/data/variable.c index 2ceeecd271..cc606cc9e7 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -54,6 +54,7 @@ struct variable struct fmt_spec write; /* Default format for WRITE. */ struct val_labs *val_labs; /* Value labels. */ char *label; /* Variable label. */ + struct string name_and_label; /* The name and label in the same string */ /* GUI information. */ enum measure measure; /* Nominal, ordinal, or continuous. */ @@ -91,9 +92,7 @@ var_create (const char *name, int width) assert (width >= 0 && width <= MAX_STRING); - v = xmalloc (sizeof *v); - v->vardict = NULL; - v->name = NULL; + v = xzalloc (sizeof *v); var_set_name (v, name); v->width = width; mv_init (&v->miss, width); @@ -103,13 +102,8 @@ var_create (const char *name, int width) v->measure = var_default_measure (type); v->display_width = var_default_display_width (width); v->print = v->write = var_default_formats (width); - v->val_labs = NULL; - v->label = NULL; - v->short_names = NULL; - v->short_name_cnt = 0; - v->aux = NULL; - v->aux_dtor = NULL; attrset_init (&v->attributes); + ds_init_empty (&v->name_and_label); return v; } @@ -160,6 +154,7 @@ var_destroy (struct variable *v) var_clear_label (v); attrset_destroy (var_get_attributes (v)); free (v->name); + ds_destroy (&v->name_and_label); free (v); } } @@ -173,6 +168,8 @@ var_get_name (const struct variable *v) return v->name; } + + /* Sets V's name to NAME, a UTF-8 encoded string. Do not use this function for a variable in a dictionary. Use dict_rename_var instead. */ @@ -184,6 +181,8 @@ var_set_name (struct variable *v, const char *name) free (v->name); v->name = xstrdup (name); + ds_destroy (&v->name_and_label); + ds_init_empty (&v->name_and_label); dict_var_changed (v); } @@ -582,14 +581,51 @@ var_default_formats (int width) ? fmt_for_output (FMT_F, 8, 2) : fmt_for_output (FMT_A, width, 0)); } + + + +/* Update the combined name and label string if necessary */ +static void +update_vl_string (const struct variable *v) +{ + /* Cast away const! */ + struct string *str = (struct string *) &v->name_and_label; + + if (ds_is_empty (str)) + { + if (v->label) + ds_put_format (str, _("%s (%s)"), v->label, v->name); + else + ds_put_cstr (str, v->name); + } +} + + /* Return a string representing this variable, in the form most appropriate from a human factors perspective, that is, its variable label if it has one, otherwise its name. */ const char * var_to_string (const struct variable *v) { - return v->label != NULL ? v->label : v->name; + enum settings_var_style style = settings_get_var_style (); + + switch (style) + { + case SETTINGS_VAR_STYLE_NAMES: + return v->name; + break; + case SETTINGS_VAR_STYLE_LABELS: + return v->label != NULL ? v->label : v->name; + break; + case SETTINGS_VAR_STYLE_BOTH: + update_vl_string (v); + return ds_cstr (&v->name_and_label); + break; + default: + NOT_REACHED (); + break; + }; } /* Returns V's variable label, or a null pointer if it has none. */ @@ -641,6 +677,9 @@ var_set_label (struct variable *v, const char *label, bool issue_warning) v->label = ss_xstrdup (s); } + ds_destroy (&v->name_and_label); + ds_init_empty (&v->name_and_label); + dict_var_changed (v); return truncated; diff --git a/src/language/utilities/set.q b/src/language/utilities/set.q index dcf7a327be..243de30063 100644 --- a/src/language/utilities/set.q +++ b/src/language/utilities/set.q @@ -108,6 +108,7 @@ int tgetnum (const char *); scripttab=string; seed=custom; tnumbers=custom; + tvars=custom; tb1=string; tbfonts=string; undefined=undef:warn/nowarn; @@ -357,6 +358,35 @@ stc_custom_tnumbers (struct lexer *lexer, } +static int +stc_custom_tvars (struct lexer *lexer, + struct dataset *ds UNUSED, + struct cmd_set *cmd UNUSED, void *aux UNUSED) +{ + lex_match (lexer, T_EQUALS); + + if (lex_match_id (lexer, "NAMES")) + { + settings_set_var_style (SETTINGS_VAR_STYLE_NAMES); + } + else if (lex_match_id (lexer, "LABELS")) + { + settings_set_var_style (SETTINGS_VAR_STYLE_LABELS); + } + else if (lex_match_id (lexer, "BOTH")) + { + settings_set_var_style (SETTINGS_VAR_STYLE_BOTH); + } + else + { + lex_error_expecting (lexer, "NAMES", "LABELS", "BOTH", NULL_SENTINEL); + return 0; + } + + return 1; +} + + /* Parses the EPOCH subcommand, which controls the epoch used for parsing 2-digit years. */ static int diff --git a/tests/language/dictionary/variable-display.at b/tests/language/dictionary/variable-display.at index 6f527a72bb..f4d76eb94b 100644 --- a/tests/language/dictionary/variable-display.at +++ b/tests/language/dictionary/variable-display.at @@ -25,3 +25,77 @@ z,Format: F8.2,,3 ,Display Width: 14,, ]) AT_CLEANUP + + +AT_BANNER([VARIABLE LABELS]) + +AT_SETUP([variable labels]) + +dnl The following test is to make sure the TVARS command works and that +dnl variables are displayed accordingly. +AT_DATA([var-labels.sps], [dnl +DATA LIST LIST NOTABLE /x * y *. +BEGIN DATA. +1 100 +2 200 +3 300 +4 400 +END DATA. + +* While no labels have been set, the TVARS is irrelevant. +SET TVARS=NAMES. +DESCRIPTIVES ALL. + +SET TVARS=LABELS. +DESCRIPTIVES ALL. + +SET TVARS=BOTH. +DESCRIPTIVES ALL. + +VARIABLE LABEL x 'foo' y 'bar'. + +* Now, the TVARS setting should have effect + +SET TVARS=NAMES. +DESCRIPTIVES ALL. + +SET TVARS=LABELS. +DESCRIPTIVES ALL. + +SET TVARS=BOTH. +DESCRIPTIVES ALL. +]) + +AT_CHECK([pspp -O format=csv var-labels.sps], [0],[dnl +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +x,4,2.50,1.29,1.00,4.00 +y,4,250.00,129.10,100.00,400.00 + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +x,4,2.50,1.29,1.00,4.00 +y,4,250.00,129.10,100.00,400.00 + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +x,4,2.50,1.29,1.00,4.00 +y,4,250.00,129.10,100.00,400.00 + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +x,4,2.50,1.29,1.00,4.00 +y,4,250.00,129.10,100.00,400.00 + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +foo,4,2.50,1.29,1.00,4.00 +bar,4,250.00,129.10,100.00,400.00 + +Table: Valid cases = 4; cases with missing value(s) = 0. +Variable,N,Mean,Std Dev,Minimum,Maximum +foo (x),4,2.50,1.29,1.00,4.00 +bar (y),4,250.00,129.10,100.00,400.00 +]) + +AT_CLEANUP -- 2.30.2