From: Ben Pfaff Date: Mon, 26 Aug 2013 05:57:56 +0000 (-0700) Subject: VARIABLE ROLE: New command. X-Git-Url: https://pintos-os.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=79100bdd30230890345c1c5a09ae57a19c1e408b;p=pspp VARIABLE ROLE: New command. Also adds GUI support. The system file representation for variable roles is really just an educated guess. I am going to ask for assistance in confirming the representation. --- diff --git a/NEWS b/NEWS index c522d1871d..352b6bfa65 100644 --- a/NEWS +++ b/NEWS @@ -6,12 +6,18 @@ Please send PSPP bug reports to bug-gnu-pspp@gnu.org. Changes after 0.8.0: + * New commands: + + - VARIABLE ROLE. + * PSPPIRE graphical user interface improvements: - Syntax windows now parse syntax in "auto" mode, which in practice should mean that both "batch" and "interactive" syntax now works, instead of just "interactive" syntax. + - The variable pane of data windows now include a Role column. + * Notable bug fixes: - System files written by IBM SPSS 21 are now read without warnings. diff --git a/doc/language.texi b/doc/language.texi index a6964ed035..e344de3019 100644 --- a/doc/language.texi +++ b/doc/language.texi @@ -502,6 +502,11 @@ Similar to print format, but used by the @cmd{WRITE} command @item Custom attributes User-defined associations between names and values. @xref{VARIABLE ATTRIBUTE}. + +@cindex variable role +@item Role +The intended role of a variable for use in dialog boxes in graphical +user interfaces. @xref{VARIABLE ROLE}. @end table @node System Variables diff --git a/doc/variables.texi b/doc/variables.texi index f4ed4449dd..1db8f034a6 100644 --- a/doc/variables.texi +++ b/doc/variables.texi @@ -23,6 +23,7 @@ several utility functions for examining and adjusting them. * VARIABLE ALIGNMENT:: Set the alignment for display. * VARIABLE WIDTH:: Set the display width. * VARIABLE LEVEL:: Set the measurement level. +* VARIABLE ROLE:: Set the role that a variable fills in analysis. * VECTOR:: Declare an array of variables. * WRITE FORMATS:: Set variable write formats. @end menu @@ -646,6 +647,42 @@ VARIABLE LEVEL Currently, this has no effect except for certain third party software. +@node VARIABLE ROLE +@section VARIABLE ROLE +@vindex VARIABLE ROLE +@display +VARIABLE ROLE + /@var{role} @var{var_list} + [/@var{role} @var{var_list}]@dots{} +@end display + +@cmd{VARIABLE ROLE} sets the intended role of a variable for use in +dialog boxes in graphical user interfaces. Each @var{role} specifies +one of the following roles for the variables that follow it: + +@table @code +@item INPUT +An input variable, such as an independent variable. + +@item TARGET +An output variable, such as an dependent variable. + +@item BOTH +A variable used for input and output. + +@item NONE +No role assigned. (This is a variable's default role.) + +@item PARTITION +Used to break the data into groups for testing. + +@item SPLIT +No meaning except for certain third party software. (This role's +meaning is unrelated to @cmd{SPLIT FILE}.) +@end table + +The PSPPIRE GUI does not yet use variable roles as intended. + @node VECTOR @section VECTOR @vindex VECTOR diff --git a/perl-module/t/Pspp.t b/perl-module/t/Pspp.t index a7fb9578da..a2d4288989 100644 --- a/perl-module/t/Pspp.t +++ b/perl-module/t/Pspp.t @@ -591,7 +591,7 @@ SYNTAX open (MYFILE, ">$tempdir/out.txt"); - foreach $k (keys %$attr) + foreach $k (sort (keys (%$attr))) { my $ll = $attr->{$k}; print MYFILE "$k =>"; @@ -600,7 +600,8 @@ SYNTAX close (MYFILE); - ok (compare ("$tempdir/out.txt", <0 colour =>blue, pink, violet nationality =>foreign size =>large diff --git a/src/data/sys-file-reader.c b/src/data/sys-file-reader.c index b3315b1e17..d38113e288 100644 --- a/src/data/sys-file-reader.c +++ b/src/data/sys-file-reader.c @@ -295,6 +295,7 @@ static void parse_data_file_attributes (struct sfm_reader *, static void parse_variable_attributes (struct sfm_reader *, const struct sfm_extension_record *, struct dictionary *); +static void assign_variable_roles (struct sfm_reader *, struct dictionary *); static void parse_long_string_value_labels (struct sfm_reader *, const struct sfm_extension_record *, struct dictionary *); @@ -524,7 +525,12 @@ sfm_open_reader (struct file_handle *fh, const char *volatile encoding, /* The following records use long names, so they need to follow renaming. */ if (extensions[EXT_VAR_ATTRS] != NULL) - parse_variable_attributes (r, extensions[EXT_VAR_ATTRS], dict); + { + parse_variable_attributes (r, extensions[EXT_VAR_ATTRS], dict); + + /* Roles use the $@Role attribute. */ + assign_variable_roles (r, dict); + } if (extensions[EXT_LONG_LABELS] != NULL) parse_long_string_value_labels (r, extensions[EXT_LONG_LABELS], dict); @@ -1896,6 +1902,64 @@ parse_variable_attributes (struct sfm_reader *r, close_text_record (r, text); } +static void +assign_variable_roles (struct sfm_reader *r, struct dictionary *dict) +{ + size_t n_warnings = 0; + size_t i; + + for (i = 0; i < dict_get_var_cnt (dict); i++) + { + struct variable *var = dict_get_var (dict, i); + struct attrset *attrs = var_get_attributes (var); + const struct attribute *attr = attrset_lookup (attrs, "$@Role"); + if (attr != NULL) + { + int value = atoi (attribute_get_value (attr, 0)); + enum var_role role; + + switch (value) + { + case 0: + role = ROLE_NONE; + break; + + case 1: + role = ROLE_INPUT; + break; + + case 2: + role = ROLE_OUTPUT; + break; + + case 3: + role = ROLE_BOTH; + break; + + case 4: + role = ROLE_PARTITION; + break; + + case 5: + role = ROLE_SPLIT; + break; + + default: + role = ROLE_NONE; + if (n_warnings++ == 0) + sys_warn (r, 0, _("Invalid role for variable %s."), + var_get_name (var)); + } + + var_set_role (var, role); + } + } + + if (n_warnings > 1) + sys_warn (r, 0, _("%zu other variables had invalid roles."), + n_warnings - 1); +} + static void check_overflow (struct sfm_reader *r, const struct sfm_extension_record *record, diff --git a/src/data/sys-file-writer.c b/src/data/sys-file-writer.c index d02369856f..1b73e737c1 100644 --- a/src/data/sys-file-writer.c +++ b/src/data/sys-file-writer.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-2000, 2006-2012 Free Software Foundation, Inc. + Copyright (C) 1997-2000, 2006-2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -259,9 +259,12 @@ sfm_open_writer (struct file_handle *fh, struct dictionary *d, write_long_string_value_labels (w, d); - if (attrset_count (dict_get_attributes (d))) - write_data_file_attributes (w, d); - write_variable_attributes (w, d); + if (opts.version >= 3) + { + if (attrset_count (dict_get_attributes (d))) + write_data_file_attributes (w, d); + write_variable_attributes (w, d); + } write_mrsets (w, d, false); @@ -680,6 +683,46 @@ write_data_file_attributes (struct sfm_writer *w, ds_destroy (&s); } +static void +add_role_attribute (enum var_role role, struct attrset *attrs) +{ + struct attribute *attr; + const char *s; + + switch (role) + { + case ROLE_NONE: + default: + s = "0"; + break; + + case ROLE_INPUT: + s = "1"; + break; + + case ROLE_OUTPUT: + s = "2"; + break; + + case ROLE_BOTH: + s = "3"; + break; + + case ROLE_PARTITION: + s = "4"; + break; + + case ROLE_SPLIT: + s = "5"; + break; + } + attrset_delete (attrs, "$@Role"); + + attr = attribute_create ("$@Role"); + attribute_add_value (attr, s); + attrset_add (attrs, attr); +} + static void write_variable_attributes (struct sfm_writer *w, const struct dictionary *d) { @@ -691,14 +734,16 @@ write_variable_attributes (struct sfm_writer *w, const struct dictionary *d) for (i = 0; i < n_vars; i++) { struct variable *v = dict_get_var (d, i); - struct attrset *attrs = var_get_attributes (v); - if (attrset_count (attrs)) - { - if (n_attrsets++) - ds_put_byte (&s, '/'); - ds_put_format (&s, "%s:", var_get_name (v)); - put_attrset (&s, attrs); - } + struct attrset attrs; + + attrset_clone (&attrs, var_get_attributes (v)); + + add_role_attribute (var_get_role (v), &attrs); + if (n_attrsets++) + ds_put_byte (&s, '/'); + ds_put_format (&s, "%s:", var_get_name (v)); + put_attrset (&s, &attrs); + attrset_destroy (&attrs); } if (n_attrsets) write_utf8_record (w, dict_get_encoding (d), &s, 18); diff --git a/src/data/variable.c b/src/data/variable.c index 720def8e6c..d3f9addc4c 100644 --- a/src/data/variable.c +++ b/src/data/variable.c @@ -58,6 +58,7 @@ struct variable /* GUI information. */ enum measure measure; /* Nominal, ordinal, or continuous. */ + enum var_role role; /* Intended use. */ int display_width; /* Width of data editor column. */ enum alignment alignment; /* Alignment of data in GUI. */ @@ -102,6 +103,7 @@ var_create (const char *name, int width) type = val_type_from_width (width); v->alignment = var_default_alignment (type); v->measure = var_default_measure (type); + v->role = ROLE_NONE; v->display_width = var_default_display_width (width); v->print = v->write = var_default_formats (width); attrset_init (&v->attributes); @@ -820,6 +822,27 @@ measure_to_string (enum measure m) } } +/* Returns a string version of measurement level M, for use in PSPP command + syntax. */ +const char * +measure_to_syntax (enum measure m) +{ + switch (m) + { + case MEASURE_NOMINAL: + return "NOMINAL"; + + case MEASURE_ORDINAL: + return "ORDINAL"; + + case MEASURE_SCALE: + return "SCALE"; + + default: + return "Invalid"; + } +} + /* Returns V's measurement level. */ enum measure var_get_measure (const struct variable *v) @@ -856,6 +879,109 @@ var_default_measure (enum val_type type) return type == VAL_NUMERIC ? MEASURE_SCALE : MEASURE_NOMINAL; } +/* Returns true if M is a valid variable role, + false otherwise. */ +bool +var_role_is_valid (enum var_role role) +{ + switch (role) + { + case ROLE_NONE: + case ROLE_INPUT: + case ROLE_OUTPUT: + case ROLE_BOTH: + case ROLE_PARTITION: + case ROLE_SPLIT: + return true; + + default: + return false; + } +} + +/* Returns a string version of ROLE, for display to a user. */ +const char * +var_role_to_string (enum var_role role) +{ + switch (role) + { + case ROLE_NONE: + return _("None"); + + case ROLE_INPUT: + return _("Input"); + + case ROLE_OUTPUT: + return _("Output"); + + case ROLE_BOTH: + return _("Both"); + + case ROLE_PARTITION: + return _("Partition"); + + case ROLE_SPLIT: + return _("Split"); + + default: + return "Invalid"; + } +} + +/* Returns a string version of ROLE, for use in PSPP comamnd syntax. */ +const char * +var_role_to_syntax (enum var_role role) +{ + switch (role) + { + case ROLE_NONE: + return "NONE"; + + case ROLE_INPUT: + return "INPUT"; + + case ROLE_OUTPUT: + return "TARGET"; + + case ROLE_BOTH: + return "BOTH"; + + case ROLE_PARTITION: + return "PARTITION"; + + case ROLE_SPLIT: + return "SPLIT"; + + default: + return ""; + } +} + +/* Returns V's role. */ +enum var_role +var_get_role (const struct variable *v) +{ + return v->role; +} + +/* Sets V's role to ROLE. */ +static void +var_set_role_quiet (struct variable *v, enum var_role role) +{ + assert (var_role_is_valid (role)); + v->role = role; +} + + +/* Sets V's role to ROLE. */ +void +var_set_role (struct variable *v, enum var_role role) +{ + struct variable *ov = var_clone (v); + var_set_role_quiet (v, role); + dict_var_changed (v, VAR_TRAIT_ROLE, ov); +} + /* Returns V's display width, which applies only to GUIs. */ int var_get_display_width (const struct variable *v) @@ -919,6 +1045,26 @@ alignment_to_string (enum alignment a) } } +/* Returns a string version of alignment A, for use in PSPP command syntax. */ +const char * +alignment_to_syntax (enum alignment a) +{ + switch (a) + { + case ALIGN_LEFT: + return "LEFT"; + + case ALIGN_RIGHT: + return "RIGHT"; + + case ALIGN_CENTRE: + return "CENTER"; + + default: + return "Invalid"; + } +} + /* Returns V's display alignment, which applies only to GUIs. */ enum alignment var_get_alignment (const struct variable *v) @@ -1150,6 +1296,7 @@ var_clone (const struct variable *old_var) var_set_value_labels_quiet (new_var, var_get_value_labels (old_var)); var_set_label_quiet (new_var, var_get_label (old_var), false); var_set_measure_quiet (new_var, var_get_measure (old_var)); + var_set_role_quiet (new_var, var_get_role (old_var)); var_set_display_width_quiet (new_var, var_get_display_width (old_var)); var_set_alignment_quiet (new_var, var_get_alignment (old_var)); var_set_leave_quiet (new_var, var_get_leave (old_var)); diff --git a/src/data/variable.h b/src/data/variable.h index a62902882f..e8f5f10146 100644 --- a/src/data/variable.h +++ b/src/data/variable.h @@ -27,7 +27,7 @@ #define VAR_TRAIT_NAME 0x0001 #define VAR_TRAIT_WIDTH 0x0002 -/* Available for reuse: 0x0004 */ +#define VAR_TRAIT_ROLE 0x0004 #define VAR_TRAIT_LABEL 0x0008 #define VAR_TRAIT_VALUE_LABELS 0x0010 #define VAR_TRAIT_MISSING_VALUES 0x0020 @@ -135,12 +135,31 @@ enum measure bool measure_is_valid (enum measure); const char *measure_to_string (enum measure); +const char *measure_to_syntax (enum measure); enum measure var_get_measure (const struct variable *); void var_set_measure (struct variable *, enum measure); enum measure var_default_measure (enum val_type); +/* Intended usage of a variable, for populating dialogs. */ +enum var_role + { + ROLE_NONE, + ROLE_INPUT, + ROLE_OUTPUT, + ROLE_BOTH, + ROLE_PARTITION, + ROLE_SPLIT + }; + +bool var_role_is_valid (enum var_role); +const char *var_role_to_string (enum var_role); +const char *var_role_to_syntax (enum var_role); + +enum var_role var_get_role (const struct variable *); +void var_set_role (struct variable *, enum var_role); + /* GUI display width. */ int var_get_display_width (const struct variable *); void var_set_display_width (struct variable *, int display_width); @@ -157,6 +176,7 @@ enum alignment bool alignment_is_valid (enum alignment); const char *alignment_to_string (enum alignment); +const char *alignment_to_syntax (enum alignment); enum alignment var_get_alignment (const struct variable *); void var_set_alignment (struct variable *, enum alignment); diff --git a/src/language/command.def b/src/language/command.def index 5191e522d7..5192d0cbf2 100644 --- a/src/language/command.def +++ b/src/language/command.def @@ -95,6 +95,7 @@ DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE ALIGNMENT", cmd_variable_alignme DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE ATTRIBUTE", cmd_variable_attribute) DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE LABELS", cmd_variable_labels) DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE LEVEL", cmd_variable_level) +DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE ROLE", cmd_variable_role) DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VARIABLE WIDTH", cmd_variable_width) DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "VECTOR", cmd_vector) DEF_CMD (S_DATA | S_INPUT_PROGRAM, 0, "WEIGHT", cmd_weight) diff --git a/src/language/dictionary/sys-file-info.c b/src/language/dictionary/sys-file-info.c index 441054e209..1ce94aa91f 100644 --- a/src/language/dictionary/sys-file-info.c +++ b/src/language/dictionary/sys-file-info.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2006, 2009, 2010, 2011, 2012, 2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -442,7 +442,7 @@ describe_variable (const struct variable *v, struct tab_table *t, int r, /* Make sure that enough rows are allocated. */ need_rows = 1; if (flags & ~(DF_DICT_INDEX | DF_VARIABLE_LABELS)) - need_rows += 15; + need_rows += 16; if (flags & DF_VALUE_LABELS) need_rows += val_labs_count (var_get_value_labels (v)); if (flags & (DF_ATTRIBUTES | DF_AT_ATTRIBUTES)) @@ -494,24 +494,28 @@ describe_variable (const struct variable *v, struct tab_table *t, int r, } } - /* Measurement level, display width, alignment. */ + /* Measurement level, role, display width, alignment. */ if (flags & DF_MISC) { - enum measure m = var_get_measure (v); - enum alignment a = var_get_alignment (v); + enum var_role role = var_get_role (v); tab_joint_text_format (t, 1, r, 2, r, TAB_LEFT, _("Measure: %s"), - m == MEASURE_NOMINAL ? _("Nominal") - : m == MEASURE_ORDINAL ? _("Ordinal") - : _("Scale")); + measure_to_string (var_get_measure (v))); r++; + + if (role != ROLE_NONE) + { + tab_joint_text_format (t, 1, r, 2, r, TAB_LEFT, + _("Role: %s"), var_role_to_string (role)); + r++; + } + tab_joint_text_format (t, 1, r, 2, r, TAB_LEFT, _("Display Alignment: %s"), - a == ALIGN_LEFT ? _("Left") - : a == ALIGN_CENTRE ? _("Center") - : _("Right")); + alignment_to_string (var_get_alignment (v))); r++; + tab_joint_text_format (t, 1, r, 2, r, TAB_LEFT, _("Display Width: %d"), var_get_display_width (v)); diff --git a/src/language/dictionary/variable-display.c b/src/language/dictionary/variable-display.c index 1ff5f46520..9e50551c92 100644 --- a/src/language/dictionary/variable-display.c +++ b/src/language/dictionary/variable-display.c @@ -1,5 +1,5 @@ /* PSPP - a program for statistical analysis. - Copyright (C) 1997-9, 2000, 2010, 2011 Free Software Foundation, Inc. + Copyright (C) 1997-9, 2000, 2010, 2011, 2013 Free Software Foundation, Inc. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -183,3 +183,40 @@ cmd_variable_level (struct lexer *lexer, struct dataset *ds) while (lex_token (lexer) != T_ENDCMD); return CMD_SUCCESS; } + +/* Set variables' role */ +int +cmd_variable_role (struct lexer *lexer, struct dataset *ds) +{ + while (lex_match (lexer, T_SLASH)) + { + struct variable **v; + size_t nv; + enum var_role role; + size_t i; + + if ( lex_match_id (lexer, "INPUT")) + role = ROLE_INPUT; + else if ( lex_match_id (lexer, "TARGET")) + role = ROLE_OUTPUT; + else if ( lex_match_id (lexer, "BOTH")) + role = ROLE_BOTH; + else if ( lex_match_id (lexer, "NONE")) + role = ROLE_NONE; + else if ( lex_match_id (lexer, "PARTITION")) + role = ROLE_PARTITION; + else if ( lex_match_id (lexer, "SPLIT")) + role = ROLE_SPLIT; + else + return CMD_FAILURE; + + if (!parse_variables (lexer, dataset_dict (ds), &v, &nv, PV_NONE)) + return CMD_FAILURE; + + for (i = 0; i < nv; i++) + var_set_role (v[i], role); + free (v); + } + + return CMD_SUCCESS; +} diff --git a/src/ui/gui/psppire-var-sheet.c b/src/ui/gui/psppire-var-sheet.c index 3a2d232002..df4718696d 100644 --- a/src/ui/gui/psppire-var-sheet.c +++ b/src/ui/gui/psppire-var-sheet.c @@ -54,7 +54,8 @@ enum vs_column VS_MISSING, VS_COLUMNS, VS_ALIGN, - VS_MEASURE + VS_MEASURE, + VS_ROLE }; G_DEFINE_TYPE (PsppireVarSheet, psppire_var_sheet, PSPP_TYPE_SHEET_VIEW); @@ -274,6 +275,21 @@ on_var_column_edited (GtkCellRendererText *cell, else if (!strcmp (new_text, measure_to_string (MEASURE_SCALE))) var_set_measure (var, MEASURE_SCALE); break; + + case VS_ROLE: + if (!strcmp (new_text, var_role_to_string (ROLE_NONE))) + var_set_role (var, ROLE_NONE); + else if (!strcmp (new_text, var_role_to_string (ROLE_INPUT))) + var_set_role (var, ROLE_INPUT); + else if (!strcmp (new_text, var_role_to_string (ROLE_OUTPUT))) + var_set_role (var, ROLE_OUTPUT); + else if (!strcmp (new_text, var_role_to_string (ROLE_BOTH))) + var_set_role (var, ROLE_BOTH); + else if (!strcmp (new_text, var_role_to_string (ROLE_PARTITION))) + var_set_role (var, ROLE_PARTITION); + else if (!strcmp (new_text, var_role_to_string (ROLE_SPLIT))) + var_set_role (var, ROLE_SPLIT); + break; } } @@ -452,6 +468,13 @@ render_var_cell (PsppSheetViewColumn *tree_column, psppire_dict_view_get_var_measurement_stock_id (var), NULL); break; + + case VS_ROLE: + g_object_set (cell, + "text", var_role_to_string (var_get_role (var)), + "editable", TRUE, + NULL); + break; } } @@ -1276,6 +1299,15 @@ psppire_var_sheet_init (PsppireVarSheet *obj) pspp_sheet_view_column_set_cell_data_func ( column, cell, render_var_cell, obj, NULL); + add_combo_column (obj, VS_ROLE, _("Role"), 12, + var_role_to_string (ROLE_NONE), ROLE_NONE, + var_role_to_string (ROLE_INPUT), ROLE_INPUT, + var_role_to_string (ROLE_OUTPUT), ROLE_OUTPUT, + var_role_to_string (ROLE_BOTH), ROLE_BOTH, + var_role_to_string (ROLE_PARTITION), ROLE_PARTITION, + var_role_to_string (ROLE_SPLIT), ROLE_SPLIT, + NULL); + pspp_sheet_view_set_rubber_banding (sheet_view, TRUE); pspp_sheet_selection_set_mode (pspp_sheet_view_get_selection (sheet_view), PSPP_SHEET_SELECTION_MULTIPLE); diff --git a/src/ui/gui/text-data-import-dialog.c b/src/ui/gui/text-data-import-dialog.c index 2559cf8b36..198a1687a8 100644 --- a/src/ui/gui/text-data-import-dialog.c +++ b/src/ui/gui/text-data-import-dialog.c @@ -162,6 +162,7 @@ apply_dict (const struct dictionary *dict, struct string *s) enum val_type type = var_get_type (var); int width = var_get_width (var); enum measure measure = var_get_measure (var); + enum var_role role = var_get_role (var); enum alignment alignment = var_get_alignment (var); const struct fmt_spec *format = var_get_print_format (var); @@ -212,16 +213,13 @@ apply_dict (const struct dictionary *dict, struct string *s) name, var_get_label (var)); if (measure != var_default_measure (type)) syntax_gen_pspp (s, "VARIABLE LEVEL %ss (%ss).\n", - name, - (measure == MEASURE_NOMINAL ? "NOMINAL" - : measure == MEASURE_ORDINAL ? "ORDINAL" - : "SCALE")); + name, measure_to_syntax (measure)); + if (role != ROLE_NONE) + syntax_gen_pspp (s, "VARIABLE ROLE /%ss %ss.\n", + var_role_to_syntax (role), name); if (alignment != var_default_alignment (type)) syntax_gen_pspp (s, "VARIABLE ALIGNMENT %ss (%ss).\n", - name, - (alignment == ALIGN_LEFT ? "LEFT" - : alignment == ALIGN_CENTRE ? "CENTER" - : "RIGHT")); + name, alignment_to_syntax (alignment)); if (var_get_display_width (var) != var_default_display_width (width)) syntax_gen_pspp (s, "VARIABLE WIDTH %ss (%d).\n", name, var_get_display_width (var)); diff --git a/tests/data/sys-file-reader.at b/tests/data/sys-file-reader.at index 35281f22e3..ab7251537e 100644 --- a/tests/data/sys-file-reader.at +++ b/tests/data/sys-file-reader.at @@ -1062,6 +1062,7 @@ dnl Variable attributes record. "FirstVariable:"; "ad"; i8 232; "le('23'"; i8 10; "'34'"; i8 10; ")"; "bert('123'"; i8 10; ")"; + "$@Role('1'"; i8 10; ")"; "/S"; i8 233; "condVariable:"; "xyzzy('quux'"; i8 10; ")"; ); @@ -1074,26 +1075,51 @@ dnl Dictionary termination record. 999; 0; ]) for variant in \ - "be c7cae57af35662acec3b945abcf7927c" \ - "le eb6b4ab9c27bfa0daa49bf2770bccb70" + "be 7fff0c04f697adf45f55d8be4aaa8712" \ + "le 7331339199344aa58bc60d7d05d538a7" do set $variant AT_CHECK_UNQUOTED([sack --$[1] sys-file.sack > sys-file.sav], [0], [], [$[2] ]) AT_DATA([sys-file.sps], [dnl GET FILE='sys-file.sav'. -DISPLAY ATTRIBUTES. +DISPLAY @ATTRIBUTES. ]) AT_CHECK([pspp -o pspp.csv sys-file.sps]) AT_CHECK([cat pspp.csv], [0], [[Variable,Description, FirstVariable,Custom attributes:, +,$@Role,1 ,adèle[1],23 ,adèle[2],34 ,bert,123 SécondVariable,Custom attributes:, ,xyzzy,quux +Table: Custom data file attributes. +Attribute,Value +Attr1[1],Value1 +Attr1[2],'déclaration' +SécondAttr[1],123 +SécondAttr[2],456 +]]) + AT_DATA([sys-file.sps], [dnl +GET FILE='sys-file.sav'. +DISPLAY DICTIONARY. +]) + AT_CHECK([pspp -o pspp.csv sys-file.sps]) + AT_CHECK([grep -v Measure pspp.csv | grep -v Display], [0], +[[Variable,Description,,Position +FirstVariable,Format: F8.0,,1 +,Role: Input,, +,Custom attributes:,, +,adèle[1],23, +,adèle[2],34, +,bert,123, +SécondVariable,Format: F8.0,,2 +,Custom attributes:,, +,xyzzy,quux, + Table: Custom data file attributes. Attribute,Value Attr1[1],Value1 diff --git a/tests/language/dictionary/variable-display.at b/tests/language/dictionary/variable-display.at index f4d76eb94b..ef545d9d16 100644 --- a/tests/language/dictionary/variable-display.at +++ b/tests/language/dictionary/variable-display.at @@ -6,6 +6,7 @@ DATA LIST FREE /x y z. VARIABLE ALIGNMENT x (LEFT)/y (RIGHT)/z (CENTER). VARIABLE WIDTH x (10)/y (12)/z (14). VARIABLE LEVEL x (SCALE)/y (ORDINAL)/z (NOMINAL). +VARIABLE ROLE /INPUT x /TARGET y /BOTH z. DISPLAY DICTIONARY. ]) AT_CHECK([pspp -o pspp.csv var-display.sps]) @@ -13,14 +14,17 @@ AT_CHECK([cat pspp.csv], [0], [dnl Variable,Description,,Position x,Format: F8.2,,1 ,Measure: Scale,, +,Role: Input,, ,Display Alignment: Left,, ,Display Width: 10,, y,Format: F8.2,,2 ,Measure: Ordinal,, +,Role: Output,, ,Display Alignment: Right,, ,Display Width: 12,, z,Format: F8.2,,3 ,Measure: Nominal,, +,Role: Both,, ,Display Alignment: Center,, ,Display Width: 14,, ]) diff --git a/tests/perl-module.at b/tests/perl-module.at index 1f4a96288c..81fca4a591 100644 --- a/tests/perl-module.at +++ b/tests/perl-module.at @@ -686,7 +686,7 @@ AT_DATA([test.pl], my $attr = $var->get_attributes (); - foreach my $k (keys %$attr) + foreach my $k (sort (keys (%$attr))) { my $ll = $attr->{$k}; print "$k =>"; @@ -694,7 +694,8 @@ AT_DATA([test.pl], } ]]) AT_CHECK([RUN_PERL_MODULE test.pl], [0], - [[colour =>blue, pink, violet + [[$@Role =>0 +colour =>blue, pink, violet nationality =>foreign size =>large ]])