mirror of
https://github.com/alexpasmantier/television.git
synced 2025-06-06 03:25:23 +00:00
refactor(shell): improve shell integration configuration syntax
This commit is contained in:
parent
c74b47d07c
commit
d3725f2cc3
@ -149,52 +149,30 @@ toggle_preview = "ctrl-o"
|
||||
# E.g. typing `git checkout <CTRL-T>` will open television with a list of
|
||||
# branches to choose from.
|
||||
|
||||
[shell_integration.commands]
|
||||
# Add your commands here. Each key is a command that will trigger tv with the
|
||||
# corresponding channel as value.
|
||||
# Example: say you want the following prompts to trigger the following channels
|
||||
[shell_integration.channel_triggers]
|
||||
# Add your channel triggers here. Each key is a channel that will be triggered
|
||||
# by the corresponding commands.
|
||||
# Example: say you want the following commands to trigger the following channels
|
||||
# when pressing <CTRL-T>:
|
||||
# `git checkout` should trigger the `git-branches` channel
|
||||
# `ls` should trigger the `dirs` channel
|
||||
# `cat` should trigger the `files` channel
|
||||
# `git checkout` should trigger the `git-branches` channel
|
||||
# `ls` should trigger the `dirs` channel
|
||||
# `cat` and `cp` should trigger the `files` channel
|
||||
#
|
||||
# You would add the following to your configuration file:
|
||||
# ```
|
||||
# [shell_integration.commands]
|
||||
# "git checkout" = "git-branch"
|
||||
# "ls" = "dirs"
|
||||
# "cat" = "files"
|
||||
# [shell_integration.channel_triggers]
|
||||
# "git-branches" = ["git checkout"]
|
||||
# "dirs" = ["ls"]
|
||||
# "files" = ["cat", "cp"]
|
||||
# ```
|
||||
"env" = ["export", "unset"]
|
||||
"dirs" = ["cd", "ls", "rmdir"]
|
||||
"files" = ["cat", "less", "head", "tail", "vim", "bat"]
|
||||
"git-diff" = ["git add"]
|
||||
"git-branch" = ["git checkout", "git branch -d"]
|
||||
"docker-images" = ["docker run"]
|
||||
"git-repos" = ["nvim"]
|
||||
|
||||
# environment variables
|
||||
"export" = "env"
|
||||
"unset" = "env"
|
||||
|
||||
# dirs channel
|
||||
"cd" = "dirs"
|
||||
"ls" = "dirs"
|
||||
"rmdir" = "dirs"
|
||||
|
||||
# files channel
|
||||
"cat" = "files"
|
||||
"less" = "files"
|
||||
"head" = "files"
|
||||
"tail" = "files"
|
||||
"vim" = "files"
|
||||
"bat" = "files"
|
||||
|
||||
# git-diff channel
|
||||
"git add" = "git-diff"
|
||||
|
||||
# git-branch channel
|
||||
"git checkout" = "git-branch"
|
||||
"git branch -d" = "git-branch"
|
||||
|
||||
# docker-images channel
|
||||
"docker run" = "docker-images"
|
||||
|
||||
# gitrepos channel
|
||||
"nvim" = "git-repos"
|
||||
|
||||
[shell_integration.keybindings]
|
||||
# controls which key binding should trigger tv
|
||||
@ -203,4 +181,3 @@ toggle_preview = "ctrl-o"
|
||||
# controls which keybinding should trigger tv
|
||||
# for command history
|
||||
"command_history" = "ctrl-r"
|
||||
|
||||
|
@ -89,7 +89,7 @@ impl Config {
|
||||
#[allow(clippy::missing_panics_doc, clippy::missing_errors_doc)]
|
||||
pub fn new() -> Result<Self> {
|
||||
// Load the default_config values as base defaults
|
||||
let default_config: Config = toml::from_str(DEFAULT_CONFIG)
|
||||
let mut default_config: Config = toml::from_str(DEFAULT_CONFIG)
|
||||
.expect("Error parsing default config");
|
||||
|
||||
// initialize the config builder
|
||||
@ -107,22 +107,35 @@ impl Config {
|
||||
let path = config_dir.join(CONFIG_FILE_NAME);
|
||||
let contents = std::fs::read_to_string(&path)?;
|
||||
|
||||
let cfg: Config = toml::from_str(&contents).unwrap_or_else(|e| {
|
||||
let mut user_cfg: Config = toml::from_str(&contents).unwrap_or_else(|e| {
|
||||
warn!(
|
||||
"Error parsing config file, using default configuration: {}" , e
|
||||
);
|
||||
default_config.clone()
|
||||
});
|
||||
|
||||
// merge shell integration triggers with commands
|
||||
default_config.shell_integration.merge_triggers();
|
||||
user_cfg.shell_integration.merge_triggers();
|
||||
// merge shell integration commands with default commands
|
||||
let mut merged_commands =
|
||||
default_config.shell_integration.commands.clone();
|
||||
merged_commands
|
||||
.extend(user_cfg.shell_integration.commands.clone());
|
||||
user_cfg.shell_integration.commands = merged_commands;
|
||||
|
||||
// merge keybindings with default keybindings
|
||||
let keybindings = merge_keybindings(
|
||||
default_config.keybindings,
|
||||
&cfg.keybindings,
|
||||
&user_cfg.keybindings,
|
||||
);
|
||||
let cfg = Config { keybindings, ..cfg };
|
||||
let final_cfg = Config {
|
||||
keybindings,
|
||||
..user_cfg
|
||||
};
|
||||
|
||||
debug!("Config: {:?}", cfg);
|
||||
Ok(cfg)
|
||||
debug!("Config: {:?}", final_cfg);
|
||||
Ok(final_cfg)
|
||||
} else {
|
||||
warn!("No config file found at {:?}, creating default configuration file at that location.", config_dir);
|
||||
// create the default configuration file in the user's config directory
|
||||
|
@ -2,13 +2,19 @@ use std::hash::Hash;
|
||||
|
||||
use crate::config::parse_key;
|
||||
use crate::event::Key;
|
||||
use crate::utils::hashmaps;
|
||||
use rustc_hash::FxHashMap;
|
||||
use serde::Deserialize;
|
||||
|
||||
#[derive(Clone, Debug, Deserialize, Default, PartialEq)]
|
||||
#[serde(default)]
|
||||
pub struct ShellIntegrationConfig {
|
||||
/// DEPRECATED: This is a legacy configuration option that is no longer used.
|
||||
/// It is kept here for backwards compatibility.
|
||||
/// {command: channel}
|
||||
pub commands: FxHashMap<String, String>,
|
||||
/// {channel: [commands]}
|
||||
pub channel_triggers: FxHashMap<String, Vec<String>>,
|
||||
pub keybindings: FxHashMap<String, String>,
|
||||
}
|
||||
|
||||
@ -19,6 +25,21 @@ impl Hash for ShellIntegrationConfig {
|
||||
}
|
||||
}
|
||||
|
||||
impl ShellIntegrationConfig {
|
||||
/// Merge the channel triggers into the commands hashmap
|
||||
/// This is done to maintain backwards compatibility with the old configuration
|
||||
/// format.
|
||||
///
|
||||
/// {command: channel} + {channel: [commands]} => {command: channel}
|
||||
pub fn merge_triggers(&mut self) {
|
||||
// invert the hashmap to get {command: channel}
|
||||
let inverted_triggers =
|
||||
hashmaps::invert_hashmap(&self.channel_triggers);
|
||||
// merge the inverted hashmap with the existing commands hashmap
|
||||
self.commands.extend(inverted_triggers);
|
||||
}
|
||||
}
|
||||
|
||||
const SMART_AUTOCOMPLETE_CONFIGURATION_KEY: &str = "smart_autocomplete";
|
||||
const COMMAND_HISTORY_CONFIGURATION_KEY: &str = "command_history";
|
||||
const DEFAULT_SHELL_AUTOCOMPLETE_KEY: char = 'T';
|
||||
|
19
television/utils/hashmaps.rs
Normal file
19
television/utils/hashmaps.rs
Normal file
@ -0,0 +1,19 @@
|
||||
use std::collections::HashMap;
|
||||
use std::hash::Hash;
|
||||
|
||||
pub fn invert_hashmap<K, V, I, S: ::std::hash::BuildHasher>(
|
||||
hashmap: &HashMap<K, V, S>,
|
||||
) -> HashMap<I, K>
|
||||
where
|
||||
K: Eq + Hash + Clone,
|
||||
V: Eq + Hash + Clone + IntoIterator<Item = I>,
|
||||
I: Eq + Hash + Clone,
|
||||
{
|
||||
let mut inverted = HashMap::new();
|
||||
for (key, values) in hashmap {
|
||||
for value in values.clone() {
|
||||
inverted.insert(value, key.clone());
|
||||
}
|
||||
}
|
||||
inverted
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
pub mod cache;
|
||||
pub mod command;
|
||||
pub mod files;
|
||||
pub mod hashmaps;
|
||||
pub mod indices;
|
||||
pub mod input;
|
||||
pub mod metadata;
|
||||
|
Loading…
x
Reference in New Issue
Block a user