improve formatting w/ nightly toolchain
nightly rustformat allows some advanced formatting for strings and imports. Add a pipeline steps that validates through this.
This commit is contained in:
parent
997b87f607
commit
0fdee55fbe
26 changed files with 271 additions and 216 deletions
51
.github/workflows/rust.yml
vendored
51
.github/workflows/rust.yml
vendored
|
@ -13,8 +13,47 @@ env:
|
|||
CARGO_TERM_COLOR: always
|
||||
|
||||
jobs:
|
||||
build:
|
||||
format_and_clippy_nightly_toolchain:
|
||||
runs-on : ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
submodules: false
|
||||
|
||||
- name: Install ubuntu dependencies
|
||||
run: |
|
||||
sudo apt update
|
||||
sudo apt install -y librust-gdk4-sys-dev \
|
||||
libglib2.0-dev libgtk-layer-shell-dev libgtk-layer-shell0 gir1.2-gtklayershell-0.1 \
|
||||
libgtk-4-dev gobject-introspection libgirepository1.0-dev gtk-doc-tools python3 valac \
|
||||
git cmake gcc meson ninja-build
|
||||
|
||||
- name: Install gt4k layer shell
|
||||
run: |
|
||||
git clone https://github.com/wmww/gtk4-layer-shell
|
||||
cd gtk4-layer-shell
|
||||
meson setup -Dexamples=true -Ddocs=true -Dtests=true build
|
||||
ninja -C build
|
||||
sudo ninja -C build install
|
||||
sudo ldconfig
|
||||
|
||||
- name: Install Rust toolchain
|
||||
uses: dtolnay/rust-toolchain@nightly
|
||||
|
||||
- name: Install format
|
||||
run: rustup component add rustfmt
|
||||
|
||||
- name: Check format with nightly rules
|
||||
run: cargo +nightly fmt -- --check --config error_on_unformatted=true,error_on_line_overflow=true,format_strings=true,group_imports=StdExternalCrate,imports_granularity=Crate
|
||||
|
||||
- name: install clippy
|
||||
run: rustup component add clippy --toolchain nightly
|
||||
|
||||
- name: run clippy nightly
|
||||
run: cargo +nightly clippy --all-targets -- -D warnings
|
||||
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
|
@ -38,11 +77,19 @@ jobs:
|
|||
sudo ninja -C build install
|
||||
sudo ldconfig
|
||||
|
||||
- name: Formatting
|
||||
- name: Install taplo toml toolkit
|
||||
run: cargo install --locked taplo-cli
|
||||
- name: Toml Formatting
|
||||
run: taplo fmt --check --diff
|
||||
|
||||
- name: Rust Formatting
|
||||
run: cargo fmt --all -- --check
|
||||
|
||||
- name: Clippy warnings
|
||||
run: cargo clippy -- -D warnings
|
||||
|
||||
- name: Build
|
||||
run: cargo build --verbose
|
||||
|
||||
- name: Run tests
|
||||
run: cargo test -- --show-output
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
[workspace]
|
||||
members = [
|
||||
"worf",
|
||||
"examples/worf-warden",
|
||||
"examples/worf-hyprswitch",
|
||||
"examples/worf-hyprspace",
|
||||
"worf",
|
||||
"examples/worf-warden",
|
||||
"examples/worf-hyprswitch",
|
||||
"examples/worf-hyprspace",
|
||||
]
|
||||
|
||||
resolver = "3"
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
worf = {path = "../../worf"}
|
||||
worf = { path = "../../worf" }
|
||||
env_logger = "0.11.8"
|
||||
hyprland = "0.4.0-beta.2"
|
||||
clap = "4.5.40"
|
||||
|
|
|
@ -385,10 +385,10 @@ fn workspace_from_selection<'a>(
|
|||
action: Option<Action>,
|
||||
max_id: i32,
|
||||
) -> Result<(WorkspaceIdentifierWithSpecial<'a>, i32, bool), String> {
|
||||
if let Some(action) = action {
|
||||
if let Some(ws) = action.workspace {
|
||||
return Ok((WorkspaceIdentifierWithSpecial::Id(ws.id), ws.id, false));
|
||||
}
|
||||
if let Some(action) = action
|
||||
&& let Some(ws) = action.workspace
|
||||
{
|
||||
return Ok((WorkspaceIdentifierWithSpecial::Id(ws.id), ws.id, false));
|
||||
}
|
||||
find_first_free_workspace_id(max_id)
|
||||
.map(|id| (WorkspaceIdentifierWithSpecial::Id(id), id, true))
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
worf = {path = "../../worf"}
|
||||
worf = { path = "../../worf" }
|
||||
env_logger = "0.11.8"
|
||||
hyprland = "0.4.0-beta.2"
|
||||
sysinfo = "0.35.2"
|
||||
|
|
|
@ -161,10 +161,10 @@ fn main() -> Result<(), String> {
|
|||
.map_err(|e| e.to_string())?;
|
||||
let update_cache = thread::spawn(move || {
|
||||
windows.iter().for_each(|item| {
|
||||
if let Some(window) = &item.data {
|
||||
if let Some(icon) = &window.icon {
|
||||
cache.insert(window.process.clone(), icon.clone());
|
||||
}
|
||||
if let Some(window) = &item.data
|
||||
&& let Some(icon) = &window.icon
|
||||
{
|
||||
cache.insert(window.process.clone(), icon.clone());
|
||||
}
|
||||
});
|
||||
let updated_toml = toml::to_string(&cache);
|
||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
|||
edition = "2024"
|
||||
|
||||
[dependencies]
|
||||
worf = {path = "../../worf"}
|
||||
worf = { path = "../../worf" }
|
||||
env_logger = "0.11.8"
|
||||
log = "0.4.27"
|
||||
serde = { version = "1.0.219", features = ["derive"] }
|
||||
|
|
|
@ -1,5 +1,3 @@
|
|||
use clap::Parser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use std::{
|
||||
collections::HashMap,
|
||||
env,
|
||||
|
@ -8,6 +6,9 @@ use std::{
|
|||
thread::sleep,
|
||||
time::Duration,
|
||||
};
|
||||
|
||||
use clap::Parser;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use worf::{
|
||||
config::{self, Config, CustomKeyHintLocation, Key},
|
||||
desktop::{copy_to_clipboard, spawn_fork},
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
lines_size_factor=1.9
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
lines_size_factor = 1.9
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
blurred_background=false
|
||||
lines_size_factor=1.9
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
blurred_background = false
|
||||
lines_size_factor = 1.9
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
blurred_background=false
|
||||
lines_size_factor=1.9
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
blurred_background = false
|
||||
lines_size_factor = 1.9
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
blurred_background=false
|
||||
lines_size_factor=1.9
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
blurred_background = false
|
||||
lines_size_factor = 1.9
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
image_size=28
|
||||
allow_images=true
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
image_size = 28
|
||||
allow_images = true
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
#blurred_background=false
|
||||
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
image_size=0
|
||||
columns=999
|
||||
allow_images=false
|
||||
orientation="Horizontal"
|
||||
row_box_orientation="Horizontal"
|
||||
content_halign="Start"
|
||||
width="100%"
|
||||
hide_scroll=true
|
||||
location=["Top"]
|
||||
lines=1
|
||||
image_size = 0
|
||||
columns = 999
|
||||
allow_images = false
|
||||
orientation = "Horizontal"
|
||||
row_box_orientation = "Horizontal"
|
||||
content_halign = "Start"
|
||||
width = "100%"
|
||||
hide_scroll = true
|
||||
location = ["Top"]
|
||||
lines = 1
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
image_size=64
|
||||
columns=6
|
||||
orientation="Vertical"
|
||||
row_box_orientation="Vertical"
|
||||
content_halign="Center"
|
||||
height="70%"
|
||||
width="60%"
|
||||
valign="Start"
|
||||
emoji_hide_label=true
|
||||
image_size = 64
|
||||
columns = 6
|
||||
orientation = "Vertical"
|
||||
row_box_orientation = "Vertical"
|
||||
content_halign = "Center"
|
||||
height = "70%"
|
||||
width = "60%"
|
||||
valign = "Start"
|
||||
emoji_hide_label = true
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
image_size=64
|
||||
columns=4
|
||||
orientation="Vertical"
|
||||
row_box_orientation="Vertical"
|
||||
content_halign="Center"
|
||||
height="105%"
|
||||
width="100%"
|
||||
valign="Start"
|
||||
blurred_background=true
|
||||
line_max_chars=32
|
||||
key_detection_type="Code"
|
||||
term="kitty -e"
|
||||
image_size = 64
|
||||
columns = 4
|
||||
orientation = "Vertical"
|
||||
row_box_orientation = "Vertical"
|
||||
content_halign = "Center"
|
||||
height = "105%"
|
||||
width = "100%"
|
||||
valign = "Start"
|
||||
blurred_background = true
|
||||
line_max_chars = 32
|
||||
key_detection_type = "Code"
|
||||
term = "kitty -e"
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
image_size=28
|
||||
allow_images=false
|
||||
term="kitty -e"
|
||||
insensitive=true
|
||||
key_detection_type="Code"
|
||||
blurred_background=false
|
||||
location=["Top"]
|
||||
lines=3
|
||||
matching="None"
|
||||
image_size = 28
|
||||
allow_images = false
|
||||
term = "kitty -e"
|
||||
insensitive = true
|
||||
key_detection_type = "Code"
|
||||
blurred_background = false
|
||||
location = ["Top"]
|
||||
lines = 3
|
||||
matching = "None"
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
image_size=48
|
||||
columns=1
|
||||
height="60%"
|
||||
width="70%"
|
||||
valign="Start"
|
||||
image_size = 48
|
||||
columns = 1
|
||||
height = "60%"
|
||||
width = "70%"
|
||||
valign = "Start"
|
||||
|
|
|
@ -50,6 +50,6 @@ rayon = "1.10.0"
|
|||
nix = { version = "0.30.0", features = ["process"] }
|
||||
emoji = "0.2.1"
|
||||
wl-clipboard-rs = "0.9.2"
|
||||
notify-rust="4.11.7"
|
||||
notify-rust = "4.11.7"
|
||||
thiserror = "2.0.12"
|
||||
urlencoding = "2.1.3"
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
use std::{env, fs, path::PathBuf, str::FromStr};
|
||||
|
||||
use clap::{Parser, ValueEnum};
|
||||
use serde::de::DeserializeOwned;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||
use serde_json::Value;
|
||||
|
||||
use crate::Error;
|
||||
|
@ -462,7 +461,9 @@ pub struct Config {
|
|||
/// set where the window is displayed.
|
||||
/// can be used to anchor a window to an edge by
|
||||
/// setting top,left for example
|
||||
#[clap(short = 'l', long = "location", value_delimiter = ',', value_parser = clap::builder::ValueParser::new(Anchor::from_str)
|
||||
#[clap(
|
||||
short = 'l', long = "location",
|
||||
value_delimiter = ',', value_parser = clap::builder::ValueParser::new(Anchor::from_str)
|
||||
)]
|
||||
location: Option<Vec<Anchor>>,
|
||||
|
||||
|
@ -1050,10 +1051,10 @@ pub fn expand_path(input: &str) -> PathBuf {
|
|||
let mut path = input.to_string();
|
||||
|
||||
// Expand ~ to home directory
|
||||
if path.starts_with('~') {
|
||||
if let Some(home_dir) = dirs::home_dir() {
|
||||
path = path.replacen('~', home_dir.to_str().unwrap_or(""), 1);
|
||||
}
|
||||
if path.starts_with('~')
|
||||
&& let Some(home_dir) = dirs::home_dir()
|
||||
{
|
||||
path = path.replacen('~', home_dir.to_str().unwrap_or(""), 1);
|
||||
}
|
||||
|
||||
// Expand $VAR style environment variables
|
||||
|
|
|
@ -1277,21 +1277,21 @@ where
|
|||
|
||||
drop(menu_rows);
|
||||
|
||||
if let Some(item) = item {
|
||||
if let Err(e) = handle_selected_item(ui, meta, None, Some(item), None) {
|
||||
log::error!("failed to handle selected item {e}");
|
||||
}
|
||||
if let Some(item) = item
|
||||
&& let Err(e) = handle_selected_item(ui, meta, None, Some(item), None)
|
||||
{
|
||||
log::error!("failed to handle selected item {e}");
|
||||
}
|
||||
} else {
|
||||
drop(menu_rows);
|
||||
}
|
||||
|
||||
if meta.config.read().unwrap().dynamic_lines() {
|
||||
if let Some(geometry) = get_monitor_geometry(ui.window.surface().as_ref()) {
|
||||
let height =
|
||||
calculate_dynamic_lines_window_height(&meta.config.read().unwrap(), ui, geometry);
|
||||
ui.window.set_height_request(height);
|
||||
}
|
||||
if meta.config.read().unwrap().dynamic_lines()
|
||||
&& let Some(geometry) = get_monitor_geometry(ui.window.surface().as_ref())
|
||||
{
|
||||
let height =
|
||||
calculate_dynamic_lines_window_height(&meta.config.read().unwrap(), ui, geometry);
|
||||
ui.window.set_height_request(height);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1310,45 +1310,43 @@ fn handle_key_expand<T>(ui: &Rc<UiElements<T>>, meta: &Rc<MetaData<T>>) -> Propa
|
|||
where
|
||||
T: Clone + Send + 'static,
|
||||
{
|
||||
if let Some(fb) = ui.main_box.selected_children().first() {
|
||||
if let Some(child) = fb.child() {
|
||||
let expander = child.downcast::<Expander>().ok();
|
||||
if let Some(expander) = expander {
|
||||
expander.set_expanded(true);
|
||||
} else {
|
||||
let data = {
|
||||
let lock = ui.menu_rows.read().unwrap();
|
||||
let menu_item = lock.get(fb);
|
||||
menu_item.map(|menu_item| {
|
||||
(
|
||||
meta.item_provider
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_sub_elements(menu_item),
|
||||
menu_item.clone(),
|
||||
)
|
||||
})
|
||||
};
|
||||
if let Some(fb) = ui.main_box.selected_children().first()
|
||||
&& let Some(child) = fb.child()
|
||||
{
|
||||
let expander = child.downcast::<Expander>().ok();
|
||||
if let Some(expander) = expander {
|
||||
expander.set_expanded(true);
|
||||
} else {
|
||||
let data = {
|
||||
let lock = ui.menu_rows.read().unwrap();
|
||||
let menu_item = lock.get(fb);
|
||||
menu_item.map(|menu_item| {
|
||||
(
|
||||
meta.item_provider
|
||||
.lock()
|
||||
.unwrap()
|
||||
.get_sub_elements(menu_item),
|
||||
menu_item.clone(),
|
||||
)
|
||||
})
|
||||
};
|
||||
|
||||
if let Some((provider_data, menu_item)) = data {
|
||||
if let Some(items) = provider_data.items {
|
||||
build_ui_from_menu_items(ui, meta, items);
|
||||
let query = match meta.expand_mode {
|
||||
ExpandMode::Verbatim => menu_item.label.clone(),
|
||||
ExpandMode::WithSpace => format!("{} ", menu_item.label.clone()),
|
||||
};
|
||||
if let Some((provider_data, menu_item)) = data {
|
||||
if let Some(items) = provider_data.items {
|
||||
build_ui_from_menu_items(ui, meta, items);
|
||||
let query = match meta.expand_mode {
|
||||
ExpandMode::Verbatim => menu_item.label.clone(),
|
||||
ExpandMode::WithSpace => format!("{} ", menu_item.label.clone()),
|
||||
};
|
||||
|
||||
set_search_text(ui, meta, &query);
|
||||
if let Ok(new_pos) = i32::try_from(query.len() + 1) {
|
||||
ui.search.set_position(new_pos);
|
||||
}
|
||||
|
||||
update_view(ui, meta, &query);
|
||||
} else if let Err(e) =
|
||||
handle_selected_item(ui, meta, None, Some(menu_item), None)
|
||||
{
|
||||
log::error!("{e}");
|
||||
set_search_text(ui, meta, &query);
|
||||
if let Ok(new_pos) = i32::try_from(query.len() + 1) {
|
||||
ui.search.set_position(new_pos);
|
||||
}
|
||||
|
||||
update_view(ui, meta, &query);
|
||||
} else if let Err(e) = handle_selected_item(ui, meta, None, Some(menu_item), None) {
|
||||
log::error!("{e}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1360,12 +1358,11 @@ fn handle_key_copy<T>(ui: &Rc<UiElements<T>>, meta: &Rc<MetaData<T>>) -> Propaga
|
|||
where
|
||||
T: Clone + Send + 'static,
|
||||
{
|
||||
if let Some(item) = get_selected_item(ui) {
|
||||
if let Some(action) = item.action {
|
||||
if let Err(e) = desktop::copy_to_clipboard(action, None) {
|
||||
log::error!("failed to copy to clipboard: {e}");
|
||||
}
|
||||
}
|
||||
if let Some(item) = get_selected_item(ui)
|
||||
&& let Some(action) = item.action
|
||||
&& let Err(e) = desktop::copy_to_clipboard(action, None)
|
||||
{
|
||||
log::error!("failed to copy to clipboard: {e}");
|
||||
}
|
||||
if let Err(e) = meta.selected_sender.send(Err(Error::NoSelection)) {
|
||||
log::error!("failed to send message {e}");
|
||||
|
@ -1445,11 +1442,11 @@ fn window_show_resize<T: Clone + 'static>(config: &Config, ui: &Rc<UiElements<T>
|
|||
return;
|
||||
};
|
||||
|
||||
if !config.blurred_background_fullscreen() {
|
||||
if let Some(background) = &ui.background {
|
||||
background.set_height_request(geometry.height());
|
||||
background.set_width_request(geometry.width());
|
||||
}
|
||||
if !config.blurred_background_fullscreen()
|
||||
&& let Some(background) = &ui.background
|
||||
{
|
||||
background.set_height_request(geometry.height());
|
||||
background.set_width_request(geometry.width());
|
||||
}
|
||||
|
||||
// Calculate target width from config, return early if not set
|
||||
|
@ -1541,7 +1538,8 @@ fn calculate_row_height<T: Clone + 'static>(
|
|||
};
|
||||
|
||||
log::debug!(
|
||||
"heights: scroll {scroll_height}, window {window_height}, keys {height_box}, height {height:?}, lines {lines:?}"
|
||||
"heights: scroll {scroll_height}, window {window_height}, keys {height_box}, height \
|
||||
{height:?}, lines {lines:?}"
|
||||
);
|
||||
|
||||
height_box
|
||||
|
@ -1574,10 +1572,10 @@ where
|
|||
if let Some(s) = ui.main_box.selected_children().into_iter().next() {
|
||||
let list_items = ui.menu_rows.read().unwrap();
|
||||
let item = list_items.get(&s);
|
||||
if let Some(selected_item) = item {
|
||||
if selected_item.visible {
|
||||
return Some(selected_item.clone());
|
||||
}
|
||||
if let Some(selected_item) = item
|
||||
&& selected_item.visible
|
||||
{
|
||||
return Some(selected_item.clone());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1728,16 +1726,15 @@ fn create_menu_row<T: Clone + 'static + Send>(
|
|||
label.set_max_width_chars(max_width_chars);
|
||||
}
|
||||
|
||||
if let Some(max_len) = meta.config.read().unwrap().line_max_chars() {
|
||||
if let Some(text) = label_text.as_ref() {
|
||||
if text.chars().count() > max_len {
|
||||
let end = text
|
||||
.char_indices()
|
||||
.nth(max_len)
|
||||
.map_or(text.len(), |(idx, _)| idx);
|
||||
label.set_text(&format!("{}...", &text[..end]));
|
||||
}
|
||||
}
|
||||
if let Some(max_len) = meta.config.read().unwrap().line_max_chars()
|
||||
&& let Some(text) = label_text.as_ref()
|
||||
&& text.chars().count() > max_len
|
||||
{
|
||||
let end = text
|
||||
.char_indices()
|
||||
.nth(max_len)
|
||||
.map_or(text.len(), |(idx, _)| idx);
|
||||
label.set_text(&format!("{}...", &text[..end]));
|
||||
}
|
||||
|
||||
row_box.append(&label);
|
||||
|
@ -1772,16 +1769,16 @@ fn create_menu_row<T: Clone + 'static + Send>(
|
|||
};
|
||||
|
||||
click.connect_pressed(move |_gesture, n_press, _x, _y| {
|
||||
if n_press == presses {
|
||||
if let Err(e) = handle_selected_item(
|
||||
if n_press == presses
|
||||
&& let Err(e) = handle_selected_item(
|
||||
&click_ui,
|
||||
&click_meta,
|
||||
None,
|
||||
Some(element_clone.clone()),
|
||||
None,
|
||||
) {
|
||||
log::error!("{e}");
|
||||
}
|
||||
)
|
||||
{
|
||||
log::error!("{e}");
|
||||
}
|
||||
});
|
||||
row.add_controller(click);
|
||||
|
@ -1963,10 +1960,10 @@ fn find_visible_child<T: Clone>(
|
|||
|
||||
for i in range {
|
||||
let i_32 = i.try_into().unwrap_or(i32::MAX);
|
||||
if let Some(child) = flow_box.child_at_index(i_32) {
|
||||
if child.is_visible() {
|
||||
return Some(child);
|
||||
}
|
||||
if let Some(child) = flow_box.child_at_index(i_32)
|
||||
&& child.is_visible()
|
||||
{
|
||||
return Some(child);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -60,10 +60,10 @@ impl AutoItemProvider {
|
|||
.is_some_and(|t| t != &AutoRunType::Auto)
|
||||
{
|
||||
let mut data = self.drun.get_elements(None);
|
||||
if let Some(items) = data.items.as_mut() {
|
||||
if let Some(mut ssh) = self.ssh.get_elements(None).items {
|
||||
items.append(&mut ssh);
|
||||
}
|
||||
if let Some(items) = data.items.as_mut()
|
||||
&& let Some(mut ssh) = self.ssh.get_elements(None).items
|
||||
{
|
||||
items.append(&mut ssh);
|
||||
}
|
||||
|
||||
self.last_mode = Some(AutoRunType::Auto);
|
||||
|
@ -77,7 +77,18 @@ impl AutoItemProvider {
|
|||
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
||||
// Regex for function names (word boundaries to match whole words)
|
||||
static MATH_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
||||
Regex::new(r"\b(sqrt|abs|exp|ln|sin|cos|tan|asin|acos|atan|atan2|sinh|cosh|tanh|asinh|acosh|atanh|floor|ceil|round|signum|min|max|pi|e|0x|0b|\||&|<<|>>|\^)\b").unwrap()
|
||||
Regex::new(
|
||||
r"\b(
|
||||
sqrt|abs|exp|ln|sin|cos|tan|
|
||||
asin|acos|atan|atan2|
|
||||
sinh|cosh|tanh|asinh|acosh|atanh|
|
||||
floor|ceil|round|signum|min|max|
|
||||
pi|e|
|
||||
0x|0b|
|
||||
\||&|<<|>>|\^
|
||||
)\b",
|
||||
)
|
||||
.unwrap()
|
||||
});
|
||||
|
||||
// Regex for strings that start with a number (including decimals)
|
||||
|
|
|
@ -7,7 +7,6 @@ use std::{
|
|||
|
||||
use freedesktop_file_parser::EntryType;
|
||||
use rayon::prelude::*;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{
|
||||
Error,
|
||||
|
@ -20,12 +19,6 @@ use crate::{
|
|||
modes::load_cache,
|
||||
};
|
||||
|
||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
||||
struct DRunCache {
|
||||
desktop_entry: String,
|
||||
run_count: usize,
|
||||
}
|
||||
|
||||
#[derive(Clone)]
|
||||
pub(crate) struct DRunProvider<T: Clone> {
|
||||
items: Option<Vec<MenuItem<T>>>,
|
||||
|
@ -78,8 +71,7 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
|||
let entries: Vec<MenuItem<T>> = find_desktop_files()
|
||||
.into_par_iter()
|
||||
.filter(|file| {
|
||||
!file.entry.no_display.unwrap_or(false)
|
||||
&& !file.entry.hidden.unwrap_or(false)
|
||||
!file.entry.no_display.unwrap_or(false) && !file.entry.hidden.unwrap_or(false)
|
||||
})
|
||||
.filter_map(|file| {
|
||||
let name = lookup_name_with_locale(
|
||||
|
@ -89,7 +81,11 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
|||
)?;
|
||||
|
||||
let (action, working_dir, in_terminal) = match &file.entry.entry_type {
|
||||
EntryType::Application(app) => (app.exec.clone(), app.path.clone(), app.terminal.unwrap_or(false)),
|
||||
EntryType::Application(app) => (
|
||||
app.exec.clone(),
|
||||
app.path.clone(),
|
||||
app.terminal.unwrap_or(false),
|
||||
),
|
||||
_ => return None,
|
||||
};
|
||||
|
||||
|
@ -104,7 +100,10 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
|||
.unwrap_or(false);
|
||||
|
||||
if !cmd_exists {
|
||||
log::warn!("Skipping desktop entry for {name:?} because action {action:?} does not exist");
|
||||
log::warn!(
|
||||
"Skipping desktop entry for {name:?} because action {action:?} does not \
|
||||
exist"
|
||||
);
|
||||
return None;
|
||||
}
|
||||
|
||||
|
@ -142,8 +141,8 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
|||
.or(icon.clone())
|
||||
.unwrap_or("application-x-executable".to_string());
|
||||
|
||||
|
||||
let action = self.get_action(in_terminal, action.exec.clone(), &action_name);
|
||||
let action =
|
||||
self.get_action(in_terminal, action.exec.clone(), &action_name);
|
||||
|
||||
entry.sub_elements.push(MenuItem::new(
|
||||
action_name,
|
||||
|
|
|
@ -137,12 +137,11 @@ impl<T: Clone> ItemProvider<T> for FileItemProvider<T> {
|
|||
if let Some(mut path_str) =
|
||||
entry.path().to_str().map(std::string::ToString::to_string)
|
||||
{
|
||||
if trimmed_search.starts_with('~') {
|
||||
if let Some(home_dir) = dirs::home_dir() {
|
||||
if let Some(home_str) = home_dir.to_str() {
|
||||
path_str = path_str.replace(home_str, "~");
|
||||
}
|
||||
}
|
||||
if trimmed_search.starts_with('~')
|
||||
&& let Some(home_dir) = dirs::home_dir()
|
||||
&& let Some(home_str) = home_dir.to_str()
|
||||
{
|
||||
path_str = path_str.replace(home_str, "~");
|
||||
}
|
||||
|
||||
if entry.path().is_dir() {
|
||||
|
|
|
@ -162,7 +162,8 @@ fn tokenize(expr: &str) -> Result<VecDeque<Token>, String> {
|
|||
i += 1;
|
||||
}
|
||||
'0'..='9' | '.' => {
|
||||
// Only insert implicit multiplication if the last token is ')' and the last token in tokens is not already an operator (except ')')
|
||||
// Only insert implicit multiplication if the last token is ')'
|
||||
// and the last token in tokens is not already an operator (except ')')
|
||||
if let Some(Token::Op(')')) = last_token {
|
||||
if let Some(Token::Op(op)) = tokens.back() {
|
||||
if *op == ')' {
|
||||
|
|
Loading…
Add table
Reference in a new issue