image rendering and visual selection

This commit is contained in:
2026-07-07 14:50:49 +02:00
parent 04b6776ebf
commit 4727e51d1b
20 changed files with 4476 additions and 2427 deletions
+23 -20
View File
@@ -8,7 +8,9 @@ use std::fs;
use std::path::PathBuf;
/// Position of the tab bar.
#[derive(Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default)]
#[derive(
Debug, Clone, Copy, PartialEq, Eq, Serialize, Deserialize, Default,
)]
#[serde(rename_all = "lowercase")]
pub enum TabBarPosition {
/// Tab bar at the top of the window.
@@ -37,7 +39,7 @@ impl Keybind {
/// - Symbol names: plus, minus, equal, bracket_left, bracket_right, etc.
pub fn parse(&self) -> Option<(bool, bool, bool, bool, String)> {
let lowercase = self.0.to_lowercase();
// Handle the special case where the key is "+" at the end
// e.g., "ctrl+alt++" should parse as ctrl+alt with key "+"
let (modifier_part, key) = if lowercase.ends_with("++") {
@@ -63,16 +65,16 @@ impl Keybind {
.unwrap_or_else(|| lowercase.clone());
("", key)
};
if key.is_empty() {
return None;
}
let mut ctrl = false;
let mut alt = false;
let mut shift = false;
let mut super_key = false;
// Parse modifiers from the modifier part
for part in modifier_part.split('+') {
match part {
@@ -81,13 +83,13 @@ impl Keybind {
"shift" => shift = true,
"super" | "meta" | "cmd" => super_key = true,
"" => {} // Empty parts from splitting
_ => {} // Unknown modifiers ignored
_ => {} // Unknown modifiers ignored
}
}
Some((ctrl, alt, shift, super_key, key))
}
/// Normalizes key names to their canonical form.
/// Supports both symbol names ("plus", "minus") and literal symbols ("+", "-").
/// Returns a static str for known keys, None for unknown (caller uses input).
@@ -98,7 +100,7 @@ impl Keybind {
"right" | "arrowright" | "arrow_right" => "right",
"up" | "arrowup" | "arrow_up" => "up",
"down" | "arrowdown" | "arrow_down" => "down",
// Other special keys
"enter" | "return" => "enter",
"tab" => "tab",
@@ -110,7 +112,7 @@ impl Keybind {
"end" => "end",
"pageup" | "page_up" | "pgup" => "pageup",
"pagedown" | "page_down" | "pgdn" => "pagedown",
// Function keys
"f1" => "f1",
"f2" => "f2",
@@ -124,7 +126,7 @@ impl Keybind {
"f10" => "f10",
"f11" => "f11",
"f12" => "f12",
// Symbol name aliases
"plus" => "+",
"minus" => "-",
@@ -283,9 +285,11 @@ impl Default for Keybindings {
impl Keybindings {
/// Builds a lookup map from parsed keybinds to actions.
pub fn build_action_map(&self) -> HashMap<(bool, bool, bool, bool, String), Action> {
pub fn build_action_map(
&self,
) -> HashMap<(bool, bool, bool, bool, String), Action> {
let mut map = HashMap::new();
let bindings: &[(&Keybind, Action)] = &[
(&self.new_tab, Action::NewTab),
(&self.next_tab, Action::NextTab),
@@ -309,13 +313,13 @@ impl Keybindings {
(&self.copy, Action::Copy),
(&self.paste, Action::Paste),
];
for (keybind, action) in bindings {
if let Some(parsed) = keybind.parse() {
map.insert(parsed, *action);
}
}
map
}
}
@@ -396,9 +400,7 @@ impl Config {
match fs::read_to_string(&config_path) {
Ok(contents) => match serde_json::from_str(&contents) {
Ok(config) => {
config
}
Ok(config) => config,
Err(e) => {
log::error!("Failed to parse config file: {}", e);
Self::default()
@@ -425,8 +427,9 @@ impl Config {
fs::create_dir_all(parent)?;
}
let json = serde_json::to_string_pretty(self)
.map_err(|e| std::io::Error::new(std::io::ErrorKind::InvalidData, e))?;
let json = serde_json::to_string_pretty(self).map_err(|e| {
std::io::Error::new(std::io::ErrorKind::InvalidData, e)
})?;
fs::write(&config_path, json)?;
Ok(())