summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--config_files/fm/tuis.yaml2
-rw-r--r--src/cli_info.rs63
-rw-r--r--src/event_exec.rs2
-rw-r--r--src/main.rs14
-rw-r--r--src/preview.rs6
-rw-r--r--src/skim.rs10
6 files changed, 63 insertions, 34 deletions
diff --git a/config_files/fm/tuis.yaml b/config_files/fm/tuis.yaml
index b880ecc..c393a9d 100644
--- a/config_files/fm/tuis.yaml
+++ b/config_files/fm/tuis.yaml
@@ -8,3 +8,5 @@ btop:
cwd: false
glances:
cwd: false
+mocp:
+ cwd: true
diff --git a/src/cli_info.rs b/src/cli_info.rs
index f8ca04a..a32a955 100644
--- a/src/cli_info.rs
+++ b/src/cli_info.rs
@@ -1,31 +1,74 @@
-use anyhow::{Context, Result};
+use std::collections::HashMap;
+use std::process::{Command, Stdio};
+
+use anyhow::{anyhow, Context, Result};
+use log::info;
use crate::impl_selectable_content;
-use crate::opener::execute_and_capture_output;
-use crate::status::Status;
use crate::utils::is_program_in_path;
+/// Holds the command line commands we can run and display
+/// without leaving FM.
+/// Those are non interactive commands displaying some info about the current
+/// file tree or setup.
#[derive(Clone)]
pub struct CliInfo {
- pub content: Vec<String>,
+ pub content: Vec<&'static str>,
+ commands: HashMap<&'static str, Vec<&'static str>>,
index: usize,
}
impl Default for CliInfo {
fn default() -> Self {
let index = 0;
- let content = vec!["duf".to_owned(), "inxi".to_owned()];
- Self { content, index }
+ let commands = HashMap::from([
+ ("duf", vec!["duf"]),
+ ("inxi", vec!["inxi", "-Fxxxcz"]),
+ ("neofetch", vec!["neofetch"]),
+ ("lsusb", vec!["lsusb"]),
+ ]);
+ let content: Vec<&'static str> = commands
+ .keys()
+ .filter(|s| is_program_in_path(s))
+ .copied()
+ .collect();
+
+ Self {
+ content,
+ index,
+ commands,
+ }
}
}
impl CliInfo {
- pub fn execute(&self, status: &Status) -> Result<String> {
- let exe = self.selected().context("no cli selected")?;
- let output = execute_and_capture_output(exe, &vec![])?;
+ /// Run the selected command and capture its output.
+ /// Some environement variables are first set to ensure the colored output.
+ /// Long running commands may freeze the display.
+ pub fn execute(&self) -> Result<String> {
+ let key = self.selected().context("no cli selected")?;
+ let output = {
+ let args = self.commands.get(key).context("no arguments for exe")?;
+ info!("execute. executable: {key}, arguments: {args:?}",);
+ let child = Command::new(args[0])
+ .args(&args[1..])
+ .env("CLICOLOR_FORCE", "1")
+ .env("COLORTERM", "ansi")
+ .stdin(Stdio::null())
+ .stdout(Stdio::piped())
+ .stderr(Stdio::null())
+ .spawn()?;
+ let output = child.wait_with_output()?;
+ if output.status.success() {
+ Ok(String::from_utf8(output.stdout)?)
+ } else {
+ Err(anyhow!("execute: command didn't finished correctly",))
+ }
+ }?;
Ok(output)
}
}
-impl_selectable_content!(String, CliInfo);
+type StaticStr = &'static str;
+impl_selectable_content!(StaticStr, CliInfo);
diff --git a/src/event_exec.rs b/src/event_exec.rs
index 5dec13b..ffe20a0 100644
--- a/src/event_exec.rs
+++ b/src/event_exec.rs
@@ -269,7 +269,7 @@ impl EventExec {
}
pub fn exec_cli_info(status: &mut Status) -> Result<()> {
- let output = status.cli_info.execute(status)?;
+ let output = status.cli_info.execute()?;
info!("output\n{output}");
status.selected().set_mode(Mode::Preview);
let preview = Preview::cli_info(&output);
diff --git a/src/main.rs b/src/main.rs
index 4d96b18..f6ec13a 100644
--- a/src/main.rs
+++ b/src/main.rs
@@ -67,17 +67,3 @@ fn main() -> Result<()> {
info!("fm is shutting down");
Ok(())
}
-
-fn main2() -> Result<()> {
- let term = Arc::new(init_term()?);
- // CLICOLOR_FORCE=1 COLORTERM="truecolor" duf > duf.txt
- let s = std::fs::read_to_string("/home/quentin/duf.txt")?;
-
- for (row, line) in s.lines().enumerate() {
- fm::skim::print_ansi_str(line, &term, Some(0), Some(row))?;
- }
- term.present()?;
- while let Ok(_ev) = term.poll_event() {}
-
- Ok(())
-}
diff --git a/src/preview.rs b/src/preview.rs
index f739c30..7fa0721 100644
--- a/src/preview.rs
+++ b/src/preview.rs
@@ -187,7 +187,7 @@ impl Preview {
Self::Text(TextContent::log(log))
}
- pub fn cli_info(output: &String) -> Self {
+ pub fn cli_info(output: &str) -> Self {
Self::ColoredText(ColoredText::new(output))
}
@@ -672,6 +672,10 @@ impl ColoredText {
self.len
}
+ pub fn is_empty(&self) -> bool {
+ self.len == 0
+ }
+
/// Make a new previewed colored text.
pub fn new(output: &str) -> Self {
let content: Vec<String> = output.lines().map(|line| line.to_owned()).collect();
diff --git a/src/skim.rs b/src/skim.rs
index ea7335b..f35b0eb 100644
--- a/src/skim.rs
+++ b/src/skim.rs
@@ -104,14 +104,8 @@ pub fn print_ansi_str(
col: Option<usize>,
row: Option<usize>,
) -> anyhow::Result<()> {
- let mut col = match col {
- Some(col) => col,
- None => 0,
- };
- let row = match row {
- Some(row) => row,
- None => 0,
- };
+ let mut col = col.unwrap_or(0);
+ let row = row.unwrap_or(0);
for (chr, attr) in skim::AnsiString::parse(text).iter() {
col += term.print_with_attr(row, col, &chr.to_string(), attr)?;
}