-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathmod.rs
More file actions
394 lines (348 loc) · 13.2 KB
/
Copy pathmod.rs
File metadata and controls
394 lines (348 loc) · 13.2 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
use cba::{
_ibog,
bait::ResultExt,
bath::{PathExt, RenamePolicy},
bo::write_str,
bog::BogOkExt,
bs::{create_dir, set_executable},
vec_,
};
use std::{collections::HashMap, path::PathBuf};
use crate::{
cli::{CliOpts, paths::*},
lessfilter::Preset,
spawn::menu_action::MenuActions,
};
use crate::{
cli::{
clap_helpers::ClapStyleOverride,
paths::{liza_path, text_renderer_path},
},
db::zoxide::HistoryConfig,
watcher::WatcherConfig,
};
use fist_types::When;
mod panes;
mod partial;
mod stash;
mod styles;
pub use panes::*;
pub use partial::*;
pub use stash::*;
pub mod ui;
use ui::StyleConfig;
// ------ CONFIG ------
#[derive(Debug, serde::Serialize, serde::Deserialize)]
#[serde(deny_unknown_fields)]
pub struct Config {
/// directory for storing history and other state.
#[serde(default = "state_dir")]
pub state_dir: PathBuf,
/// cache directory.
#[serde(default = "cache_dir")]
pub cache_dir: PathBuf,
/// A container for settings whose values are accessed at runtime.
/// Its fields are included directly in (flattened into) the config.
#[serde(flatten, default)]
pub global: GlobalConfig,
/// All styling options not governed by the match-maker cfg
#[serde(default)]
pub styles: StyleConfig,
/// Configure the filesystem watcher
#[serde(default)]
pub notify: WatcherConfig,
/// Miscellaneous and Tool specific options
#[serde(default)]
pub misc: MiscConfig,
/// Settings related to saving to and retrieving from history.
#[serde(default)]
pub history: HistoryConfig,
/// Custom actions which appear in the menu
#[serde(default)]
pub actions: MenuActions,
/// Custom stash modes
#[serde(default)]
pub stash: StashLogicConfig,
}
impl Default for Config {
fn default() -> Self {
toml::from_str(include_str!("../../assets/config/config.toml")).unwrap()
}
}
#[derive(Debug, Default, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct GlobalConfig {
pub interface: InterfaceConfig,
/// Configure behavior of filesystem actions.
pub fs: FsConfig,
/// Configure behavior of the fd tool.
/// This affects [FsAction::Find](`crate::run::FsAction::Find`) and the default subcommand.
pub fd: FdConfig,
/// Configure behavior of the rg tool.
/// This affects [FsAction::Rg](`crate::run::FsAction::Rg`) and the rg subcommand.
pub rg: RgConfig,
/// Configure various pane related settings.
pub panes: PanesConfig,
/// Matchmaker styling overrides (per-pane).
/// [Warning!]: Unstable and untested.
pub mm: MatchmakerOverrides,
}
/// Miscellaneous and Tool specific options.
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct MiscConfig {
/// How long to wait between consecutive clipboard actions
pub clipboard_delay_ms: u64,
/// Overwrite or append logs on application start.
pub append_mode_logging: bool,
/// Overwrite or append tool logs on application start.
pub tools_append_mode_logging: bool,
/// Pass the spawning command to this instead of invoking it directly.
pub spawn_with: Vec<String>,
/// The default output fromat when calling [FsAction::Print]
pub output_template: Option<String>,
/// The seperator used between calls to [FsAction::Print]
pub output_separator: String,
pub list_absolute_paths: bool,
}
impl Default for MiscConfig {
fn default() -> Self {
Self {
clipboard_delay_ms: 20,
append_mode_logging: false,
tools_append_mode_logging: false,
spawn_with: Vec::new(),
output_template: None,
output_separator: "\n".into(),
list_absolute_paths: false,
}
}
}
// -------------- GLOBAL --------------
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
/// Settings related to the behavior of the main interface.
/// It is recommended not to change these.
pub struct InterfaceConfig {
// actions
/// The command template to execute when [FsAction::Advance](`crate::run::FsAction::Advance`) is invoked on a file.
pub advance_command: String,
/// If true, the functions of the Accept and Print actions will be swapped.
pub alt_accept: bool,
/// Disables multi-accept.
pub no_multi_accept: bool,
/// When outside the prompt, whether to register paste as characters or an action.
pub always_paste: bool,
pub move_cursor_with_advance_and_parent_in_prompt: bool,
// display
/// The prefix to display when the cursor is in the prompt.
pub cwd_prompt: String,
/// Display a toast when current directory has no entries. (TODO)
pub toast_on_empty: bool,
/// If [AutoJump](`crate::run::FsAction::AutoJump`) should accept or advance
pub autojump_advance: bool,
pub dim_prompt: bool,
pub dim_status: bool,
}
impl Default for InterfaceConfig {
fn default() -> Self {
Self {
alt_accept: false,
no_multi_accept: false,
always_paste: false,
advance_command: Preset::Edit.to_command_string(When::Auto),
cwd_prompt: "{} ".into(),
toast_on_empty: true,
autojump_advance: false,
dim_prompt: false,
dim_status: true,
move_cursor_with_advance_and_parent_in_prompt: false,
}
}
}
#[derive(Default, Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct FdConfig {
/// A map of folders => exclusion globs which should be applied when in them.
/// ~ can be used in lieu of $HOME.
/// If a list is specified for the empty path "", that list will override the list of default exclusions for the platform, and apply everywhere.
/// Only one value (exclusion list) can apply to each path.
pub exclusions: HashMap<PathBuf, Vec<String>>,
/// Arguments added to every fd command
pub base_args: Vec<String>,
/// When no path is given to fs, such as using `fs [pattern]`, whether to search in `$HOME` or the current directory.
pub default_search_in_home: bool,
/// Enabling this will hide ignored files when a pattern but no path is given to fs, such as using `fs [pattern]`, provided that ignore was not explicitly specified to the cli.
pub default_search_ignore: bool,
// ---------------- Experimental/Nonstandard ---------------
/// When given a set of paths to search with `fs`, change the working directory to their common denominator.
pub reduce_paths: bool,
/// The set of arguments applied to the end of `fs ::` when no `fd_args` were given.
pub default_args: Vec<String>,
/// - Auto: When the pattern for fs :: starts with a dot and is followed only by alphanumeric characters, and -h is not specified, include hidden files.
/// - Always: When query for fs :: starts with a dot and is followed only by alphanumeric characters, and -h/-I are not specified, include hidden/ignored files respectively.
/// - Never: No change.
///
/// Additionally, when this setting is not Never, hidden visibility is automatically turned on when starting a nav pane in a directory containing only hidden files.
pub dot_query_show_hidden: When,
}
#[derive(Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct RgConfig {
/// A map of folders => globs which should be applied when in them.
/// ~ can be used in lieu of $HOME.
/// If a list is specified for the empty path "", that list will apply everywhere.
/// Only one value can apply to each path.
/// Multiple glob flags may be used. Globbing rules match .gitignore globs. Precede a glob with a ! to exclude it. If multiple globs match a file or directory, the glob given later in the command line takes precedence. Globs used via this flag are matched case insensitively. This is passed on to rg through the `--iglob` parameter.
pub iglobs: HashMap<PathBuf, Vec<String>>,
/// Arguments added to every rg command
pub base_args: Vec<String>,
/// Query when no patterns are provided. Starting with '-v ' adds the -v flag.
pub empty_pattern: Option<String>,
/// The set of arguments applied to the end of `fs :` when no `rg_args` were given.
pub default_args: Vec<String>,
}
impl Default for RgConfig {
fn default() -> Self {
RgConfig {
iglobs: Default::default(),
base_args: vec_![
"--trim",
"--color=ansi",
"--no-context-separator",
"--field-context-separator=-",
],
empty_pattern: None,
default_args: Default::default(),
}
}
}
#[derive(Default, Debug, Clone, PartialEq, serde::Serialize, serde::Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct FsConfig {
pub rename_policy: RenamePolicy,
}
// -------------- IMPL --------------------------
impl Config {
pub fn override_from(
&mut self,
cli: &CliOpts,
) {
let style = &mut self.styles.path;
match cli.style {
ClapStyleOverride::Auto => {
// leave config unchanged
}
ClapStyleOverride::None => {
style.file_icons = false;
style.file_colors = false;
style.dir_icons = false;
style.dir_colors = false;
}
ClapStyleOverride::IconColors => {
style.file_icons = true;
style.dir_icons = true;
style.icon_colors = true;
style.file_colors = true;
style.dir_colors = true;
}
ClapStyleOverride::Icons => {
style.file_icons = true;
style.dir_icons = true;
style.file_colors = false;
style.dir_colors = false;
}
ClapStyleOverride::Colors => {
style.file_icons = false;
style.dir_icons = false;
style.file_colors = true;
style.dir_colors = true;
}
ClapStyleOverride::All => {
style.file_icons = true;
style.file_colors = true;
style.dir_icons = true;
style.dir_colors = true;
}
}
if let Some(r) = cli.fullscreen {
self.global.mm.fullscreen = true;
self.global.mm.reverse = r.map(|s| !s);
}
if cli.alt_accept {
self.global.interface.alt_accept = !self.global.interface.alt_accept
}
}
// --------------------------------------------------
pub fn db_path(&self) -> PathBuf {
#[cfg(debug_assertions)]
{
self.state_dir.join("dev.db")
}
#[cfg(not(debug_assertions))]
{
self.state_dir.join("record.db")
}
}
pub fn log_path(&self) -> PathBuf {
self.state_dir.join(format!("{BINARY_FULL}.log"))
}
pub fn tools_log_path(&self) -> PathBuf {
self.state_dir.join(format!("{BINARY_FULL}.tools.log"))
}
pub fn check_dirs_or_exit(&self) {
let dirs = [&self.state_dir, &self.cache_dir];
for dir in dirs {
log::debug!("checking: {dir:?}");
if !create_dir(dir) {
std::process::exit(1)
}
}
}
// initialize helper files
pub fn check_scripts(
&self,
force: bool,
) {
let files = [
(liza_path(), include_str!("../../assets/scripts/liza")),
(
text_renderer_path(),
include_str!("../../assets/scripts/pager"),
),
(
show_error_path(),
include_str!("../../assets/scripts/fist_show_error"),
),
];
for (path, script) in files {
let error_prefix = format!("Failed set executability of {path:?}");
if (force || !path.exists())
&& write_str(path, script)._ebog().is_some()
&& set_executable(path).prefix(&error_prefix)._ebog().is_some()
{
if !force
// less noise for debug
{
_ibog!("{} saved to: {}", path.basename(), path.to_string_lossy());
}
}
}
}
}
#[cfg(test)]
mod tests {
use crate::{lessfilter::LessfilterConfig, run::mm_config::MMConfig};
use super::*;
#[test]
fn deserialize_configs() {
let _: Config = toml::from_str(include_str!("../../assets/config/config.toml")).unwrap();
let _: Config = toml::from_str(include_str!("../../assets/config/dev.toml")).unwrap();
let _: LessfilterConfig =
toml::from_str(include_str!("../../assets/config/lessfilter.toml")).unwrap();
let _: LessfilterConfig =
toml::from_str(include_str!("../../assets/config/lessfilter.dev.toml")).unwrap();
let _: MMConfig = toml::from_str(include_str!("../../assets/config/mm.toml")).unwrap();
let _: MMConfig = toml::from_str(include_str!("../../assets/config/mm.dev.toml")).unwrap();
}
}