summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKyohei Uto <im@kyoheiu.dev>2024-01-27 15:48:30 +0900
committerKyohei Uto <im@kyoheiu.dev>2024-01-27 15:48:30 +0900
commitfbca88780ea1c157667ba7ef2cb8f7c5369fdaa5 (patch)
treef25f0e382c14cb0c0914b2ca4fc93a945adc14d4
parent622a6c79ff4558d320fd1392070b91c9b19f7512 (diff)
Read config inside felix and update it
-rw-r--r--src/config.rs2
-rw-r--r--src/run.rs50
-rw-r--r--src/state.rs126
3 files changed, 67 insertions, 111 deletions
diff --git a/src/config.rs b/src/config.rs
index fffe626..ca20ffd 100644
--- a/src/config.rs
+++ b/src/config.rs
@@ -75,7 +75,7 @@ impl Default for Config {
}
}
-fn read_config(p: &Path) -> Result<ConfigWithPath, 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(ConfigWithPath {
diff --git a/src/run.rs b/src/run.rs
index 0362ad0..9e85f54 100644
--- a/src/run.rs
+++ b/src/run.rs
@@ -1,5 +1,4 @@
-#![allow(unreachable_code)]
-use super::config::FELIX;
+use super::config::{read_config, FELIX};
use super::errors::FxError;
use super::functions::*;
use super::layout::{PreviewType, Split};
@@ -18,6 +17,8 @@ use std::env;
use std::io::{stdout, Write};
use std::panic;
use std::path::PathBuf;
+use std::sync::{Arc, Mutex};
+use std::thread;
use std::time::Instant;
const TRASH: &str = "Trash";
@@ -169,7 +170,52 @@ fn _run(mut state: State, session_path: PathBuf) -> Result<(), FxError> {
}
screen.flush()?;
+ // Spawn another thread to watch the config file.
+ let mut modified_time = match &state.config_path {
+ Some(config_path) => config_path.metadata().unwrap().modified().ok(),
+ None => None,
+ };
+ let config_updated = Arc::new(Mutex::new(false));
+ let config_updated_in_another_tread = config_updated.clone();
+ let config_path_in_another_thread = state.config_path.clone();
+ // if config file does not exist, no watching.
+ if modified_time.is_some() {
+ // Every 2 secondes, check if the config file is updated.
+ thread::spawn(move || loop {
+ thread::sleep(std::time::Duration::from_secs(2));
+ if *config_updated_in_another_tread.lock().unwrap() {
+ continue;
+ }
+ let metadata = config_path_in_another_thread.as_ref().unwrap().metadata();
+ if let Ok(metadata) = metadata {
+ let new_modified = metadata.modified().ok();
+ if modified_time != new_modified {
+ if let Ok(mut updated) = config_updated_in_another_tread.lock() {
+ *updated = true;
+ modified_time = new_modified;
+ } else {
+ break;
+ }
+ }
+ }
+ });
+ }
+
'main: loop {
+ // Check if config file is updated
+ if let Ok(mut should_be_updated) = config_updated.lock() {
+ if *should_be_updated {
+ if let Ok(c) = read_config(state.config_path.as_ref().unwrap()) {
+ state.set_config(c.config);
+ state.redraw(state.layout.y);
+ print_info("New config set.", state.layout.y);
+ } else {
+ print_warning("Something wrong with the config file.", state.layout.y);
+ }
+ *should_be_updated = false;
+ }
+ }
+
if state.is_out_of_bounds() {
state.layout.nums.reset();
state.redraw(BEGINNING_ROW);
diff --git a/src/state.rs b/src/state.rs
index 7c14273..78fbaf5 100644
--- a/src/state.rs
+++ b/src/state.rs
@@ -15,7 +15,7 @@ use chrono::prelude::*;
use crossterm::event::KeyEventKind;
use crossterm::event::{Event, KeyCode, KeyEvent};
use crossterm::style::Stylize;
-use log::{error, info};
+use log::info;
use std::collections::VecDeque;
use std::collections::{BTreeMap, BTreeSet};
use std::env;
@@ -41,7 +41,7 @@ use std::os::unix::fs::PermissionsExt;
pub const BEGINNING_ROW: u16 = 3;
pub const EMPTY_WARNING: &str = "Are you sure to empty the trash directory? (if yes: y)";
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct State {
pub list: Vec<ItemInfo>,
pub current_dir: PathBuf,
@@ -63,7 +63,7 @@ pub struct State {
pub is_ro: bool,
}
-#[derive(Debug)]
+#[derive(Debug, Default)]
pub struct Registers {
pub unnamed: Vec<ItemBuffer>,
pub zero: Vec<ItemBuffer>,
@@ -243,95 +243,30 @@ impl State {
(None, Config::default())
}
};
+ let mut state = State::default();
+ state.set_config(config.clone());
- let session = read_session(session_path);
- 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);
- };
-
- let (time_start, name_max) = make_layout(original_column);
-
- let color = config.color.unwrap_or_default();
-
- let split = session.split.unwrap_or(Split::Vertical);
-
- let has_bat = check_bat();
- let has_chafa = check_chafa();
let has_zoxide = check_zoxide();
- let is_kitty = check_kitty_support();
Ok(State {
- list: Vec::new(),
- registers: Registers {
- unnamed: vec![],
- zero: vec![],
- numbered: VecDeque::new(),
- named: BTreeMap::new(),
- },
- operations: Operation {
- pos: 0,
- op_list: Vec::new(),
- },
- current_dir: PathBuf::new(),
- trash_dir: PathBuf::new(),
config_path,
- lwd_file: None,
- match_vim_exit_behavior: config.match_vim_exit_behavior.unwrap_or_default(),
has_zoxide,
- default: config
- .default
- .unwrap_or_else(|| env::var("EDITOR").unwrap_or_default()),
- commands: to_extension_map(&config.exec),
- layout: 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,
- colors: ConfigColor {
- dir_fg: color.dir_fg,
- file_fg: color.file_fg,
- symlink_fg: color.symlink_fg,
- dirty_fg: color.dirty_fg,
- },
- sort_by: session.sort_by,
- show_hidden: session.show_hidden,
- side: if session.preview.unwrap_or(false) {
- Side::Preview
- } else {
- Side::None
- },
- split,
- preview_start: match split {
- Split::Vertical => (0, 0),
- Split::Horizontal => (0, 0),
- },
- preview_space: match split {
- Split::Vertical => (0, 0),
- Split::Horizontal => (0, 0),
- },
- has_bat,
- has_chafa,
- is_kitty,
- },
- jumplist: JumpList::default(),
- c_memo: Vec::new(),
- p_memo: Vec::new(),
- keyword: None,
- v_start: None,
- is_ro: false,
+ layout: Layout::new(session_path, config)?,
+ ..state
})
}
+ /// Set configuration from config file.
+ pub fn set_config(&mut self, config: Config) {
+ let color = config.color.unwrap_or_default();
+ self.match_vim_exit_behavior = config.match_vim_exit_behavior.unwrap_or_default();
+ self.default = config
+ .default
+ .unwrap_or_else(|| env::var("EDITOR").unwrap_or_default());
+ self.commands = to_extension_map(&config.exec);
+ self.layout.colors = color;
+ }
+
/// Select item that the cursor points to.
pub fn get_item(&self) -> Result<&ItemInfo, FxError> {
self.list
@@ -1928,22 +1863,6 @@ fn read_item(entry: fs::DirEntry) -> ItemInfo {
// Ok(result)
// }
-/// 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 zoxide is installed.
fn check_zoxide() -> bool {
std::process::Command::new("zoxide")
@@ -1952,15 +1871,6 @@ fn check_zoxide() -> bool {
.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
- }
-}
-
/// Set content type from ItemInfo.
fn set_preview_content_type(item: &mut ItemInfo) {
if item.file_size > MAX_SIZE_TO_PREVIEW {