cirho / powerline-rust

powerline-shell written in Rust
MIT License
51 stars 25 forks source link

Give me the choice between easier configuration and slightly faster performance #25

Open SIGSTACKFAULT opened 1 year ago

SIGSTACKFAULT commented 1 year ago

I want my config to be easy to install.
It would be much more convenient if I could have a file like ~/.config/powerline-rust.yaml.

Proposal: Look for a config file at runtime and use it if present, otherwise use compiled-in default prompt. Checking if a file exists should take negligible time and i'm pretty sure the kernel caches it.

Optional: have a feature which decides whether it even looks for a config file at runtime

If you want the slight speed advantage of a compile-time prompt, then you can compile your prompt in and not have a config file. If you want the easyness of a config file, you can just use the file.

SIGSTACKFAULT commented 1 year ago

Threw this together in like two hours. full of placeholders but gets what i mean across

# $HOME/.config/powerline-rust.yaml
segments:
  - user
  - host
  - cwd:
      max_length: 20
      wanted_seg_num: 4
      resolve_symlinks: false
  - git

diff --git a/Cargo.lock b/Cargo.lock
index 3472541..35fe596 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -186,6 +186,12 @@ dependencies = [
  "vcpkg",
 ]

+[[package]]
+name = "linked-hash-map"
+version = "0.5.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "0717cef1bc8b636c6e1c1bbdefc09e6322da8a9321966e8928ef80d20f7f770f"
+
 [[package]]
 name = "log"
 version = "0.4.20"
@@ -234,6 +240,7 @@ dependencies = [
  "hostname",
  "libc",
  "users",
+ "yaml-rust",
 ]

 [[package]]
@@ -486,3 +493,12 @@ name = "windows_x86_64_msvc"
 version = "0.48.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "ed94fce61571a4006852b7389a063ab983c02eb1bb37b47f8272ce92d06d9538"
+
+[[package]]
+name = "yaml-rust"
+version = "0.4.5"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "56c1936c4cc7a1c9ab21a1ebb602eb942ba868cbd44a99cb7cdc5892335e1c85"
+dependencies = [
+ "linked-hash-map",
+]
diff --git a/Cargo.toml b/Cargo.toml
index a7656c6..ff5c830 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -10,6 +10,7 @@ libc = "0.2"
 hostname = "0.3"
 git2 = { version = "0.18", optional = true, default-features = false }
 chrono = { version = "0.4.29", optional = true }
+yaml-rust = "0.4.5"

 [features]
 default = ["bash-shell", "libgit"]
diff --git a/src/bin/powerline.rs b/src/bin/powerline.rs
index 416c241..3178ed5 100644
--- a/src/bin/powerline.rs
+++ b/src/bin/powerline.rs
@@ -4,8 +4,24 @@ extern crate powerline;
 use powerline::modules::Time;
 use powerline::modules::*;
 use powerline::theme::SimpleTheme;
+use powerline::Powerline;
+use std::env;
+use std::fs;
+use yaml_rust::Yaml;
+use yaml_rust::YamlLoader;

 fn main() {
+    let config_file = config_file().unwrap();
+    println!("config_file {}", config_file);
+    let prompt: Powerline = match prompt_from_file(&config_file) {
+        Some(prompt) => prompt,
+        None => default_prompt(),
+    };
+
+    println!("{} ", prompt)
+}
+
+fn default_prompt() -> Powerline {
     let mut prompt = powerline::Powerline::new();

     #[cfg(feature = "time")]
@@ -19,6 +35,45 @@ fn main() {
     prompt.add_module(Cmd::<SimpleTheme>::new());
     // prompt.add_module(VirtualEnv::<SimpleTheme>::new())?;
     // prompt.add_module(ExitCode::<SimpleTheme>::new())?;
+    return prompt;
+}

-    println!("{} ", prompt);
+/**
+ * Get the config file we should use
+ * checks $XDG_CONFIG_HOME, then $HOME/.config/
+ */
+fn config_file() -> Option<String> {
+    let xdg_config_home = env::var("XDG_CONFIG_HOME");
+    let home = env::var("HOME");
+    match xdg_config_home {
+        Ok(path) => Some(path + "powerline-rust.yaml"),
+        Err(_) => match home {
+            Ok(path) => Some(path + "/.config/powerline-rust.yaml"),
+            Err(_) => None,
+        },
+    }
+}
+
+fn prompt_from_file(filename: &str) -> Option<Powerline> {
+    let mut prompt = powerline::Powerline::new();
+    // prompt.add_module(Cwd::<SimpleTheme>::new(10, 2, false));
+    let contents = fs::read_to_string(filename).ok()?;
+    let docs = YamlLoader::load_from_str(&contents).ok()?;
+    let doc = &docs.get(0)?;
+    let segments = doc["segments"].as_vec()?;
+    for segment in segments.iter() {
+        println!("segment {:?}", segment);
+        match segment {
+            Yaml::String(s) => match s.as_str() {
+                "host" => prompt.add_module(Host::<SimpleTheme>::new()),
+                "user" => prompt.add_module(User::<SimpleTheme>::new()),
+                "git" => prompt.add_module(Git::<SimpleTheme>::new()),
+                _ => panic!(),
+            },
+            _ => {
+                println!("todo: {:?}", segment);
+            },
+        }
+    }
+    return Some(prompt);
 }