Skip to main content

pspp/
settings.rs

1// PSPP - a program for statistical analysis.
2// Copyright (C) 2025 Free Software Foundation, Inc.
3//
4// This program is free software: you can redistribute it and/or modify it under
5// the terms of the GNU General Public License as published by the Free Software
6// Foundation, either version 3 of the License, or (at your option) any later
7// version.
8//
9// This program is distributed in the hope that it will be useful, but WITHOUT
10// ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11// FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
12// details.
13//
14// You should have received a copy of the GNU General Public License along with
15// this program.  If not, see <http://www.gnu.org/licenses/>.
16
17use std::sync::{Arc, OnceLock};
18
19use binrw::Endian;
20use enum_map::EnumMap;
21use serde::Serialize;
22
23use crate::{
24    format::{F8_2, Format, Settings as FormatSettings},
25    message::Severity,
26    output::pivot::look::Look,
27};
28
29/// Whether to show variable or value labels or the underlying value or variable
30/// name.
31#[derive(Copy, Clone, Debug, Default, PartialEq, Eq, Serialize)]
32#[serde(rename_all = "snake_case")]
33pub enum Show {
34    /// Value (or variable name) only.
35    Value,
36
37    /// Label only.
38    ///
39    /// The value will be shown if no label is available.
40    #[default]
41    Label,
42
43    /// Value (or variable name) and label.
44    ///
45    /// Just the value will be shown, if no label is available.
46    Both,
47}
48
49impl Show {
50    pub fn show_value(&self) -> bool {
51        *self != Self::Label
52    }
53
54    pub fn show_label(&self) -> bool {
55        *self != Self::Value
56    }
57}
58
59#[derive(Copy, Clone, PartialEq, Eq)]
60pub struct EndianSettings {
61    /// Endianness for reading IB, PIB, and RB formats.
62    pub input: Endian,
63
64    /// Endianness for writing IB, PIB, and RB formats.
65    pub output: Endian,
66}
67
68impl Default for EndianSettings {
69    fn default() -> Self {
70        Self {
71            input: Endian::NATIVE,
72            output: Endian::NATIVE,
73        }
74    }
75}
76
77impl EndianSettings {
78    pub const fn new(endian: Endian) -> Self {
79        Self {
80            input: endian,
81            output: endian,
82        }
83    }
84}
85
86pub struct Settings {
87    pub look: Arc<Look>,
88
89    /// `MDISPLAY`: how to display matrices in `MATRIX`...`END MATRIX`.
90    pub matrix_display: MatrixDisplay,
91
92    pub view_length: usize,
93    pub view_width: usize,
94    pub safer: bool,
95    pub include: bool,
96    pub route_errors_to_terminal: bool,
97    pub route_errors_to_listing: bool,
98    pub scompress: bool,
99    pub undefined: bool,
100    pub blanks: Option<f64>,
101    pub max_messages: EnumMap<Severity, usize>,
102    pub printback: bool,
103    pub macros: MacroSettings,
104    pub max_loops: usize,
105    pub workspace: usize,
106    pub default_format: Format,
107    pub testing: bool,
108    pub fuzz_bits: usize,
109    pub scale_min: usize,
110    pub commands: Compatibility,
111    pub global: Compatibility,
112    pub syntax: Compatibility,
113    pub formats: FormatSettings,
114    pub endian: EndianSettings,
115    pub small: f64,
116    pub show_values: Show,
117    pub show_variables: Show,
118}
119
120impl Default for Settings {
121    fn default() -> Self {
122        Self {
123            look: Arc::new(Look::default()),
124            matrix_display: MatrixDisplay::default(),
125            view_length: 24,
126            view_width: 79,
127            safer: false,
128            include: true,
129            route_errors_to_terminal: true,
130            route_errors_to_listing: true,
131            scompress: true,
132            undefined: true,
133            blanks: None,
134            max_messages: EnumMap::from_fn(|_| 100),
135            printback: true,
136            macros: MacroSettings::default(),
137            max_loops: 40,
138            workspace: 64 * 1024 * 1024,
139            default_format: F8_2,
140            testing: false,
141            fuzz_bits: 6,
142            scale_min: 24,
143            commands: Compatibility::default(),
144            global: Compatibility::default(),
145            syntax: Compatibility::default(),
146            formats: Default::default(),
147            endian: EndianSettings::default(),
148            small: 0.0001,
149            show_values: Show::default(),
150            show_variables: Show::default(),
151        }
152    }
153}
154
155impl Settings {
156    pub fn global() -> &'static Settings {
157        static GLOBAL: OnceLock<Settings> = OnceLock::new();
158        GLOBAL.get_or_init(Settings::default)
159    }
160}
161
162#[derive(Copy, Clone, PartialEq, Eq, Default)]
163pub enum Compatibility {
164    /// Use improved PSPP behavior.
165    #[default]
166    Enhanced,
167
168    /// Be as compatible as possible.
169    Compatible,
170}
171
172pub struct MacroSettings {
173    /// Expand macros?
174    pub expand: bool,
175
176    /// Print macro expansions?
177    pub print_expansions: bool,
178
179    /// Maximum iterations of `!FOR`.
180    pub max_iterations: usize,
181
182    /// Maximum nested macro expansion levels.
183    pub max_nest: usize,
184}
185
186impl Default for MacroSettings {
187    fn default() -> Self {
188        Self {
189            expand: true,
190            print_expansions: false,
191            max_iterations: 1000,
192            max_nest: 50,
193        }
194    }
195}
196
197/// How to display matrices in `MATRIX`...`END MATRIX`.
198#[derive(Default)]
199pub enum MatrixDisplay {
200    /// Output matrices as text.
201    #[default]
202    Text,
203
204    /// Output matrices as pivot tables.
205    Tables,
206}
207
208pub enum OutputType {
209    /// Errors and warnings.
210    Error,
211
212    /// Notes.
213    Notes,
214
215    /// Syntax printback.
216    Syntax,
217
218    /// Everything else.
219    Other,
220}