Make workspace names case-insensitive

This commit is contained in:
Ivan Molodetskikh 2024-05-16 10:54:24 +04:00
parent eb9bbe3352
commit 109d99fe82
3 changed files with 67 additions and 32 deletions

View File

@ -1502,14 +1502,15 @@ impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName {
ctx: &mut knuffel::decode::Context<S>,
) -> Result<WorkspaceName, DecodeError<S>> {
#[derive(Debug)]
struct WorkspaceNameSet(HashSet<String>);
struct WorkspaceNameSet(Vec<String>);
match &**val {
knuffel::ast::Literal::String(ref s) => {
let mut name_set: HashSet<String> = match ctx.get::<WorkspaceNameSet>() {
let mut name_set: Vec<String> = match ctx.get::<WorkspaceNameSet>() {
Some(h) => h.0.clone(),
None => HashSet::new(),
None => Vec::new(),
};
if !name_set.insert(s.clone().to_string()) {
if name_set.iter().any(|name| name.eq_ignore_ascii_case(s)) {
ctx.emit_error(DecodeError::unexpected(
val,
"named workspace",
@ -1517,6 +1518,8 @@ impl<S: knuffel::traits::ErrorSpan> knuffel::DecodeScalar<S> for WorkspaceName {
));
return Ok(Self(String::new()));
}
name_set.push(s.to_string());
ctx.set(WorkspaceNameSet(name_set));
Ok(Self(s.clone().into()))
}

View File

@ -531,7 +531,11 @@ impl<W: LayoutElement> Layout<W> {
MonitorSet::NoOutputs { workspaces } => {
let ws = workspaces
.iter_mut()
.find(|ws| ws.name.as_deref() == Some(workspace_name))
.find(|ws| {
ws.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
.unwrap();
ws.add_window(window, true, width, is_full_width);
None
@ -799,22 +803,23 @@ impl<W: LayoutElement> Layout<W> {
match &self.monitor_set {
MonitorSet::Normal { ref monitors, .. } => {
for mon in monitors {
if let Some((index, workspace)) = mon
.workspaces
.iter()
.enumerate()
.find(|(_, w)| w.name.as_deref() == Some(workspace_name))
if let Some((index, workspace)) =
mon.workspaces.iter().enumerate().find(|(_, w)| {
w.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
{
return Some((index, workspace));
}
}
}
MonitorSet::NoOutputs { workspaces } => {
if let Some((index, workspace)) = workspaces
.iter()
.enumerate()
.find(|(_, w)| w.name.as_deref() == Some(workspace_name))
{
if let Some((index, workspace)) = workspaces.iter().enumerate().find(|(_, w)| {
w.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
}) {
return Some((index, workspace));
}
}
@ -837,7 +842,11 @@ impl<W: LayoutElement> Layout<W> {
}
MonitorSet::NoOutputs { workspaces } => {
for (idx, ws) in workspaces.iter_mut().enumerate() {
if ws.name.as_deref() == Some(workspace_name) {
if ws
.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
{
ws.unname();
// Clean up empty workspaces.
@ -1110,10 +1119,11 @@ impl<W: LayoutElement> Layout<W> {
};
monitors.iter().find(|monitor| {
monitor
.workspaces
.iter()
.any(|ws| ws.name.as_deref() == Some(workspace_name))
monitor.workspaces.iter().any(|ws| {
ws.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
})
}
@ -1416,7 +1426,7 @@ impl<W: LayoutElement> Layout<W> {
use crate::layout::monitor::WorkspaceSwitch;
let mut seen_workspace_id = HashSet::new();
let mut seen_workspace_name = HashSet::new();
let mut seen_workspace_name = Vec::<String>::new();
let (monitors, &primary_idx, &active_monitor_idx) = match &self.monitor_set {
MonitorSet::Normal {
@ -1443,9 +1453,12 @@ impl<W: LayoutElement> Layout<W> {
if let Some(name) = &workspace.name {
assert!(
seen_workspace_name.insert(name),
!seen_workspace_name
.iter()
.any(|n| n.eq_ignore_ascii_case(name)),
"workspace name must be unique"
);
seen_workspace_name.push(name.clone());
}
workspace.verify_invariants();
@ -1544,9 +1557,12 @@ impl<W: LayoutElement> Layout<W> {
if let Some(name) = &workspace.name {
assert!(
seen_workspace_name.insert(name),
!seen_workspace_name
.iter()
.any(|n| n.eq_ignore_ascii_case(name)),
"workspace name must be unique"
);
seen_workspace_name.push(name.clone());
}
workspace.verify_invariants();
@ -2788,7 +2804,11 @@ mod tests {
}
}
if ws.name.as_deref() == Some(&ws_name) {
if ws
.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(&ws_name))
{
found_workspace = true;
}
}
@ -2802,7 +2822,11 @@ mod tests {
}
}
if ws.name.as_deref() == Some(&ws_name) {
if ws
.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(&ws_name))
{
found_workspace = true;
}
}

View File

@ -104,15 +104,19 @@ impl<W: LayoutElement> Monitor<W> {
}
pub fn find_named_workspace(&self, workspace_name: &str) -> Option<&Workspace<W>> {
self.workspaces
.iter()
.find(|w| w.name.as_deref() == Some(workspace_name))
self.workspaces.iter().find(|ws| {
ws.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
}
pub fn find_named_workspace_index(&self, workspace_name: &str) -> Option<usize> {
self.workspaces
.iter()
.position(|w| w.name.as_deref() == Some(workspace_name))
self.workspaces.iter().position(|ws| {
ws.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
})
}
pub fn active_workspace(&mut self) -> &mut Workspace<W> {
@ -227,7 +231,11 @@ impl<W: LayoutElement> Monitor<W> {
pub fn unname_workspace(&mut self, workspace_name: &str) -> bool {
for ws in &mut self.workspaces {
if ws.name.as_deref() == Some(workspace_name) {
if ws
.name
.as_ref()
.map_or(false, |name| name.eq_ignore_ascii_case(workspace_name))
{
ws.unname();
return true;
}