Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Features around config #271

Merged
merged 12 commits into from
Jan 27, 2024
9 changes: 8 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,13 @@

## Unreleased

### Added

- `:config` to point to the config file if exists.
- felix listens to the change of the config file, and re-read the config automatically.
- Refactor around `State::new()`.
- Add `config_path` field to `State`.

## v2.11.1 (2023-12-10)

### Fixed
Expand Down Expand Up @@ -34,7 +41,7 @@
- Add `FxError::InvalidPath` to handle invalid unicode in file path.

## v2.9.0 (2023-10-22)

### Added
- Change color of untracked/changed files or directories containing such files. Default color is Red(1). You can change it in the config file.
- Add `git2`.
Expand Down
64 changes: 15 additions & 49 deletions src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,51 +9,11 @@ pub const FELIX: &str = "felix";
const CONFIG_FILE: &str = "config.yaml";
const CONFIG_FILE_ANOTHER_EXT: &str = "config.yml";

#[allow(dead_code)]
const CONFIG_EXAMPLE: &str = r###"
# Default exec command when open files.
# If not set, will default to $EDITOR.
# default: nvim

# Whether to match the behavior of vim exit keybindings
# i.e. `ZQ` exits without cd to LWD (Last Working Directory) while `ZZ` cd to LWD
# match_vim_exit_behavior: false

# key (the command you want to use when opening files): [values] (extensions)
# In the key, You can use arguments.
# exec:
# zathura:
# [pdf]
# 'feh -.':
# [jpg, jpeg, png, gif, svg, hdr]

# The foreground color of directory, file and symlink.
# Pick one of the following:
# Black // 0
# Red // 1
# Green // 2
# Yellow // 3
# Blue // 4
# Magenta // 5
# Cyan // 6
# White // 7
# LightBlack // 8
# LightRed // 9
# LightGreen // 10
# LightYellow // 11
# LightBlue // 12
# LightMagenta // 13
# LightCyan // 14
# LightWhite // 15
# Rgb(u8, u8, u8)
# AnsiValue(u8)
# Default to LightCyan(dir), LightWhite(file), LightYellow(symlink) and Red(changed/untracked files in git repositories).
# color:
# dir_fg: LightCyan
# file_fg: LightWhite
# symlink_fg: LightYellow
# dirty_fg: Red
"###;
#[derive(Debug, Clone)]
pub struct ConfigWithPath {
pub config_path: Option<PathBuf>,
pub config: Config,
}

#[derive(Deserialize, Debug, Clone)]
pub struct Config {
Expand Down Expand Up @@ -115,13 +75,16 @@ impl Default for Config {
}
}

fn read_config(p: &Path) -> Result<Config, FxError> {
pub fn read_config(p: &Path) -> Result<ConfigWithPath, FxError> {
let s = read_to_string(p)?;
let deserialized: Config = serde_yaml::from_str(&s)?;
Ok(deserialized)
Ok(ConfigWithPath {
config_path: Some(p.to_path_buf()),
config: deserialized,
})
}

pub fn read_config_or_default() -> Result<Config, FxError> {
pub fn read_config_or_default() -> Result<ConfigWithPath, FxError> {
//First, declare default config file path.
let (config_file_path1, config_file_path2) = {
let mut config_path = {
Expand Down Expand Up @@ -172,6 +135,9 @@ pub fn read_config_or_default() -> Result<Config, FxError> {
if let Some(config_file) = config_file {
read_config(&config_file)
} else {
Ok(Config::default())
Ok(ConfigWithPath {
config_path: None,
config: Config::default(),
})
}
}
81 changes: 77 additions & 4 deletions src/layout.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,11 @@ use super::config::*;
use super::errors::FxError;
use super::functions::*;
use super::nums::*;
use super::session::SortKey;
use super::session::{read_session, SortKey};
use super::state::{ItemInfo, BEGINNING_ROW};
use super::term::*;

use log::error;
use serde::{Deserialize, Serialize};

pub const MAX_SIZE_TO_PREVIEW: u64 = 1_000_000_000;
Expand All @@ -16,7 +17,7 @@ pub const PROPER_WIDTH: u16 = 28;
pub const TIME_WIDTH: u16 = 16;
const EXTRA_SPACES: u16 = 3;

#[derive(Debug)]
#[derive(Debug, Default)]
pub struct Layout {
pub nums: Num,
pub y: u16,
Expand Down Expand Up @@ -46,20 +47,67 @@ pub enum PreviewType {
Binary,
}

#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone)]
#[derive(Debug, PartialEq, PartialOrd, Eq, Ord, Clone, Default)]
pub enum Side {
#[default]
Preview,
Reg,
None,
}

#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone, Copy)]
#[derive(Debug, PartialEq, Eq, Deserialize, Serialize, Clone, Copy, Default)]
pub enum Split {
#[default]
Vertical,
Horizontal,
}

impl Layout {
pub fn new(session_path: &std::path::Path, config: Config) -> Result<Self, FxError> {
let (original_column, original_row) = terminal_size()?;
// Return error if terminal size may cause panic
if original_column < 4 {
error!("Too small terminal size (less than 4 columns).");
return Err(FxError::TooSmallWindowSize);
};
if original_row < 4 {
error!("Too small terminal size. (less than 4 rows)");
return Err(FxError::TooSmallWindowSize);
};

// Prepare state fields.
let (time_start, name_max) = make_layout(original_column);
let session = read_session(session_path);
let split = session.split.unwrap_or_default();
let has_bat = check_bat();
let has_chafa = check_chafa();
let is_kitty = check_kitty_support();

let colors = config.color.unwrap_or_default();

Ok(Layout {
nums: Num::new(),
y: BEGINNING_ROW,
terminal_row: original_row,
terminal_column: original_column,
name_max_len: name_max,
time_start_pos: time_start,
sort_by: session.sort_by,
show_hidden: session.show_hidden,
side: match session.preview.unwrap_or(false) {
true => Side::Preview,
false => Side::None,
},
split,
preview_start: (0, 0),
preview_space: (0, 0),
has_bat,
has_chafa,
is_kitty,
colors,
})
}

pub fn is_preview(&self) -> bool {
self.side == Side::Preview
}
Expand Down Expand Up @@ -364,3 +412,28 @@ pub fn make_layout(column: u16) -> (u16, usize) {
(time_start, name_max)
}
}

/// Check if bat is installed.
fn check_bat() -> bool {
std::process::Command::new("bat")
.arg("--help")
.output()
.is_ok()
}

/// Check if chafa is installed.
fn check_chafa() -> bool {
std::process::Command::new("chafa")
.arg("--help")
.output()
.is_ok()
}

/// Check if the terminal is Kitty or not
fn check_kitty_support() -> bool {
if let Ok(term) = std::env::var("TERM") {
term.contains("kitty")
} else {
false
}
}
2 changes: 1 addition & 1 deletion src/nums.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
#[derive(Clone, Copy, Debug)]
#[derive(Clone, Copy, Debug, Default)]
pub struct Num {
pub index: usize,
pub skip: u16,
Expand Down
2 changes: 1 addition & 1 deletion src/op.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use super::state::ItemBuffer;
use log::info;
use std::path::PathBuf;

#[derive(Debug, Clone)]
#[derive(Debug, Default, Clone)]
pub struct Operation {
pub pos: usize,
pub op_list: Vec<OpKind>,
Expand Down
Loading
Loading