tabby 0.0.6

A fast, lightweight windows powershell tab completion library.
Documentation
use anyhow::Result;
use miniserde::{json, Deserialize, Serialize};
use std::{
    fmt::{self, Display},
    path::{Path, PathBuf},
};

pub mod setup;

pub struct Completions {
    pub completions: Vec<String>,
}

impl Display for Completions {
    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> fmt::Result {
        let last = self.completions.len() - 1;

        for (index, completion) in self.completions.iter().enumerate() {
            if index == last {
                write!(f, "{}", completion)?;
            } else {
                writeln!(f, "{}", completion)?;
            }
        }

        Ok(())
    }
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CompletionData {
    #[serde(rename = "cli-name")]
    /// Name used to invoke the CLI.
    pub cli_name: String,
    /// Completion items used for generating tab completions.
    pub commands: Option<Vec<CompletionItem>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
pub struct CompletionItem {
    /// Name of the command.
    pub name: String,
    /// List of flags supported by the command.
    pub flags: Vec<String>,
}

pub struct Completer {
    /// Data tabby uses to generate tab completions.
    pub completion_data: CompletionData,
    /// Path to `tabby.config.json`.
    pub config_path: PathBuf,
}

impl Completer {
    pub fn new<P: AsRef<Path>>(config_path: P) -> Result<Completer> {
        let text = std::fs::read_to_string(&config_path).unwrap();
        let completion_data = json::from_str::<CompletionData>(&text)?;

        let completer = Completer {
            config_path: config_path.as_ref().to_owned(),
            completion_data,
        };

        Ok(completer)
    }

    pub fn from<P: AsRef<Path>>(p: P) -> Result<Completer> {
        Self::new(p.as_ref().to_owned())
    }

    pub fn get_completions(&self) -> Completions {
        let args = std::env::args().collect::<Vec<String>>();
        let mut completions = vec![];

        if args.len() > 2 {
            let current_word = args[2].replace("--word=", "");

            let mut line = args[4].to_string();

            let position = args[6].parse::<u64>().unwrap();

            if position > line.len() as u64 {
                line.push_str(" ");
            }

            let split = line.split(" ").collect::<Vec<&str>>();

            match split.len() {
                2 => {
                    // volt.exe
                    if current_word == "" {
                        for command in self.completion_data.commands.as_ref().unwrap().iter() {
                            completions.push(command.name.to_string());
                        }
                    } else {
                        for command in self.completion_data.commands.as_ref().unwrap().iter() {
                            if command.name.starts_with(&current_word) {
                                completions.push(command.name.to_string());
                            }
                        }
                    }
                }
                _ => {
                    // volt.exe --verbose or volt.exe install

                    if current_word.starts_with("--") || current_word == "" {
                        for command in self.completion_data.commands.as_ref().unwrap().iter() {
                            if command.name == split[1] {
                                for flag in command.flags.iter() {
                                    if flag.starts_with(&current_word) {
                                        completions.push(flag.to_string());
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }

        Completions { completions }
    }

    pub fn install(&self) -> Result<()> {
        setup::install(&self)?;
        Ok(())
    }

    pub fn display_completions(completions: &Vec<String>) {
        for completion in completions.iter() {
            println!("{}", completion);
        }
    }
}