tokei/config.rs
1use std::{env, fs, path::PathBuf};
2
3use etcetera::BaseStrategy;
4
5use crate::language::LanguageType;
6use crate::sort::Sort;
7use crate::stats::Report;
8
9/// A configuration struct for how [`Languages::get_statistics`] searches and
10/// counts languages.
11///
12/// ```
13/// use tokei::Config;
14///
15/// let config = Config {
16/// treat_doc_strings_as_comments: Some(true),
17/// ..Config::default()
18/// };
19/// ```
20///
21/// [`Languages::get_statistics`]: struct.Languages.html#method.get_statistics
22#[derive(Debug, Default, Deserialize)]
23pub struct Config {
24 /// Width of columns to be printed to the terminal. _This option is ignored
25 /// in the library._ *Default:* Auto detected width of the terminal.
26 pub columns: Option<usize>,
27 /// Count hidden files and directories. *Default:* `false`.
28 pub hidden: Option<bool>,
29 /// Don't respect ignore files (.gitignore, .ignore, etc.). This implies --no-ignore-parent,
30 /// --no-ignore-dot, and --no-ignore-vcs. *Default:* `false`.
31 pub no_ignore: Option<bool>,
32 /// Don't respect ignore files (.gitignore, .ignore, etc.) in parent directories.
33 /// *Default:* `false`.
34 pub no_ignore_parent: Option<bool>,
35 /// Don't respect .ignore and .tokeignore files, including those in parent directories.
36 /// *Default:* `false`.
37 pub no_ignore_dot: Option<bool>,
38 /// Don't respect VCS ignore files (.gitignore, .hgignore, etc.), including those in
39 /// parent directories. *Default:* `false`.
40 pub no_ignore_vcs: Option<bool>,
41 /// Whether to treat doc strings in languages as comments. *Default:*
42 /// `false`.
43 pub treat_doc_strings_as_comments: Option<bool>,
44 /// Sort languages. *Default:* `None`.
45 pub sort: Option<Sort>,
46 /// Filters languages searched to just those provided. E.g. A directory
47 /// containing `C`, `Cpp`, and `Rust` with a `Config.types` of `[Cpp, Rust]`
48 /// will count only `Cpp` and `Rust`. *Default:* `None`.
49 pub types: Option<Vec<LanguageType>>,
50 // /// A map of individual language configuration.
51 // pub languages: Option<HashMap<LanguageType, LanguageConfig>>,
52 /// Whether to output only the paths for downstream batch processing
53 /// *Default:* false
54 #[serde(skip)]
55 /// Adds a closure for each function, e.g., print the result
56 pub for_each_fn: Option<fn(LanguageType, Report)>,
57}
58
59impl Config {
60 /// Constructs a new `Config` from either `$base/tokei.toml` or
61 /// `$base/.tokeirc`. `tokei.toml` takes precedence over `.tokeirc`
62 /// as the latter is a hidden file on Unix and not an idiomatic
63 /// filename on Windows.
64 fn get_config(base: PathBuf) -> Option<Self> {
65 fs::read_to_string(base.join("tokei.toml"))
66 .ok()
67 .or_else(|| fs::read_to_string(base.join(".tokeirc")).ok())
68 .and_then(|s| toml::from_str(&s).ok())
69 }
70
71 /// Creates a `Config` from three configuration files if they are available.
72 /// Files can have two different names `tokei.toml` and `.tokeirc`.
73 /// Firstly it will attempt to find a config in the configuration directory
74 /// (see below), secondly from the home directory, `$HOME/`,
75 /// and thirdly from the current directory, `./`.
76 /// The current directory's configuration will take priority over the configuration
77 /// directory.
78 ///
79 /// |Platform | Value | Example |
80 /// | ------- | ------------------------------------- | ------------------------------ |
81 /// | Linux | `$XDG_CONFIG_HOME` or `$HOME`/.config | /home/alice/.config |
82 /// | macOS | `$XDG_CONFIG_HOME` or `$HOME`/.config | /Users/alice/.config |
83 /// | Windows | `{FOLDERID_RoamingAppData}` | C:\Users\Alice\AppData\Roaming |
84 ///
85 /// # Example
86 /// ```toml
87 /// columns = 80
88 /// types = ["Python"]
89 /// treat_doc_strings_as_comments = true
90 // ///
91 // /// [[languages.Python]]
92 // /// extensions = ["py3"]
93 /// ```
94 pub fn from_config_files() -> Self {
95 let conf_dir = etcetera::choose_base_strategy()
96 .ok()
97 .map(|basedirs| basedirs.config_dir())
98 .and_then(Self::get_config)
99 .unwrap_or_default();
100
101 let home_dir = etcetera::home_dir()
102 .ok()
103 .and_then(Self::get_config)
104 .unwrap_or_default();
105
106 let current_dir = env::current_dir()
107 .ok()
108 .and_then(Self::get_config)
109 .unwrap_or_default();
110
111 #[allow(clippy::or_fun_call)]
112 Config {
113 columns: current_dir
114 .columns
115 .or(home_dir.columns.or(conf_dir.columns)),
116 hidden: current_dir.hidden.or(home_dir.hidden.or(conf_dir.hidden)),
117 //languages: current_dir.languages.or(conf_dir.languages),
118 treat_doc_strings_as_comments: current_dir.treat_doc_strings_as_comments.or(home_dir
119 .treat_doc_strings_as_comments
120 .or(conf_dir.treat_doc_strings_as_comments)),
121 sort: current_dir.sort.or(home_dir.sort.or(conf_dir.sort)),
122 types: current_dir.types.or(home_dir.types.or(conf_dir.types)),
123 for_each_fn: current_dir
124 .for_each_fn
125 .or(home_dir.for_each_fn.or(conf_dir.for_each_fn)),
126 no_ignore: current_dir
127 .no_ignore
128 .or(home_dir.no_ignore.or(conf_dir.no_ignore)),
129 no_ignore_parent: current_dir
130 .no_ignore_parent
131 .or(home_dir.no_ignore_parent.or(conf_dir.no_ignore_parent)),
132 no_ignore_dot: current_dir
133 .no_ignore_dot
134 .or(home_dir.no_ignore_dot.or(conf_dir.no_ignore_dot)),
135 no_ignore_vcs: current_dir
136 .no_ignore_vcs
137 .or(home_dir.no_ignore_vcs.or(conf_dir.no_ignore_vcs)),
138 }
139 }
140}
141
142/*
143/// Configuration for an individual [`LanguageType`].
144///
145/// ```
146/// use std::collections::HashMap;
147/// use tokei::{Config, LanguageConfig, LanguageType};
148///
149/// let config = Config {
150/// languages: {
151/// let cpp_conf = LanguageConfig {
152/// extensions: vec![String::from("c")],
153/// };
154///
155/// let mut languages_config = HashMap::new();
156/// languages_config.insert(LanguageType::Cpp, cpp_conf);
157///
158/// Some(languages_config)
159/// },
160///
161/// ..Config::default()
162/// };
163///
164/// ```
165///
166/// [`LanguageType`]: enum.LanguageType.html
167#[derive(Debug, Default, Deserialize)]
168pub struct LanguageConfig {
169 /// Additional extensions for a language. Any extensions that overlap with
170 /// already defined extensions from `tokei` will be ignored.
171 pub extensions: Vec<String>,
172}
173
174impl LanguageConfig {
175 /// Creates a new empty configuration. By default this will not change
176 /// anything from the default.
177 pub fn new() -> Self {
178 Self::default()
179 }
180
181 /// Accepts a `Vec<String>` representing additional extensions for a
182 /// language. Any extensions that overlap with already defined extensions
183 /// from `tokei` will be ignored.
184 pub fn extensions(&mut self, extensions: Vec<String>) {
185 self.extensions = extensions;
186 }
187}
188*/