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
|
CARGO_TERM_COLOR: always
|
||||||
|
|
||||||
jobs:
|
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
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
steps:
|
steps:
|
||||||
|
@ -38,11 +77,19 @@ jobs:
|
||||||
sudo ninja -C build install
|
sudo ninja -C build install
|
||||||
sudo ldconfig
|
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
|
run: cargo fmt --all -- --check
|
||||||
|
|
||||||
- name: Clippy warnings
|
- name: Clippy warnings
|
||||||
run: cargo clippy -- -D warnings
|
run: cargo clippy -- -D warnings
|
||||||
|
|
||||||
- name: Build
|
- name: Build
|
||||||
run: cargo build --verbose
|
run: cargo build --verbose
|
||||||
|
|
||||||
- name: Run tests
|
- name: Run tests
|
||||||
run: cargo test -- --show-output
|
run: cargo test -- --show-output
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
[workspace]
|
[workspace]
|
||||||
members = [
|
members = [
|
||||||
"worf",
|
"worf",
|
||||||
"examples/worf-warden",
|
"examples/worf-warden",
|
||||||
"examples/worf-hyprswitch",
|
"examples/worf-hyprswitch",
|
||||||
"examples/worf-hyprspace",
|
"examples/worf-hyprspace",
|
||||||
]
|
]
|
||||||
|
|
||||||
resolver = "3"
|
resolver = "3"
|
||||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
worf = {path = "../../worf"}
|
worf = { path = "../../worf" }
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
hyprland = "0.4.0-beta.2"
|
hyprland = "0.4.0-beta.2"
|
||||||
clap = "4.5.40"
|
clap = "4.5.40"
|
||||||
|
|
|
@ -385,10 +385,10 @@ fn workspace_from_selection<'a>(
|
||||||
action: Option<Action>,
|
action: Option<Action>,
|
||||||
max_id: i32,
|
max_id: i32,
|
||||||
) -> Result<(WorkspaceIdentifierWithSpecial<'a>, i32, bool), String> {
|
) -> Result<(WorkspaceIdentifierWithSpecial<'a>, i32, bool), String> {
|
||||||
if let Some(action) = action {
|
if let Some(action) = action
|
||||||
if let Some(ws) = action.workspace {
|
&& let Some(ws) = action.workspace
|
||||||
return Ok((WorkspaceIdentifierWithSpecial::Id(ws.id), ws.id, false));
|
{
|
||||||
}
|
return Ok((WorkspaceIdentifierWithSpecial::Id(ws.id), ws.id, false));
|
||||||
}
|
}
|
||||||
find_first_free_workspace_id(max_id)
|
find_first_free_workspace_id(max_id)
|
||||||
.map(|id| (WorkspaceIdentifierWithSpecial::Id(id), id, true))
|
.map(|id| (WorkspaceIdentifierWithSpecial::Id(id), id, true))
|
||||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
worf = {path = "../../worf"}
|
worf = { path = "../../worf" }
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
hyprland = "0.4.0-beta.2"
|
hyprland = "0.4.0-beta.2"
|
||||||
sysinfo = "0.35.2"
|
sysinfo = "0.35.2"
|
||||||
|
|
|
@ -161,10 +161,10 @@ fn main() -> Result<(), String> {
|
||||||
.map_err(|e| e.to_string())?;
|
.map_err(|e| e.to_string())?;
|
||||||
let update_cache = thread::spawn(move || {
|
let update_cache = thread::spawn(move || {
|
||||||
windows.iter().for_each(|item| {
|
windows.iter().for_each(|item| {
|
||||||
if let Some(window) = &item.data {
|
if let Some(window) = &item.data
|
||||||
if let Some(icon) = &window.icon {
|
&& let Some(icon) = &window.icon
|
||||||
cache.insert(window.process.clone(), icon.clone());
|
{
|
||||||
}
|
cache.insert(window.process.clone(), icon.clone());
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
let updated_toml = toml::to_string(&cache);
|
let updated_toml = toml::to_string(&cache);
|
||||||
|
|
|
@ -4,7 +4,7 @@ version = "0.1.0"
|
||||||
edition = "2024"
|
edition = "2024"
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
worf = {path = "../../worf"}
|
worf = { path = "../../worf" }
|
||||||
env_logger = "0.11.8"
|
env_logger = "0.11.8"
|
||||||
log = "0.4.27"
|
log = "0.4.27"
|
||||||
serde = { version = "1.0.219", features = ["derive"] }
|
serde = { version = "1.0.219", features = ["derive"] }
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
use clap::Parser;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use std::{
|
use std::{
|
||||||
collections::HashMap,
|
collections::HashMap,
|
||||||
env,
|
env,
|
||||||
|
@ -8,6 +6,9 @@ use std::{
|
||||||
thread::sleep,
|
thread::sleep,
|
||||||
time::Duration,
|
time::Duration,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
use clap::Parser;
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use worf::{
|
use worf::{
|
||||||
config::{self, Config, CustomKeyHintLocation, Key},
|
config::{self, Config, CustomKeyHintLocation, Key},
|
||||||
desktop::{copy_to_clipboard, spawn_fork},
|
desktop::{copy_to_clipboard, spawn_fork},
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
lines_size_factor=1.9
|
lines_size_factor = 1.9
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
blurred_background=false
|
blurred_background = false
|
||||||
lines_size_factor=1.9
|
lines_size_factor = 1.9
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
blurred_background=false
|
blurred_background = false
|
||||||
lines_size_factor=1.9
|
lines_size_factor = 1.9
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
blurred_background=false
|
blurred_background = false
|
||||||
lines_size_factor=1.9
|
lines_size_factor = 1.9
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=true
|
allow_images = true
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
#blurred_background=false
|
#blurred_background=false
|
||||||
|
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
image_size=0
|
image_size = 0
|
||||||
columns=999
|
columns = 999
|
||||||
allow_images=false
|
allow_images = false
|
||||||
orientation="Horizontal"
|
orientation = "Horizontal"
|
||||||
row_box_orientation="Horizontal"
|
row_box_orientation = "Horizontal"
|
||||||
content_halign="Start"
|
content_halign = "Start"
|
||||||
width="100%"
|
width = "100%"
|
||||||
hide_scroll=true
|
hide_scroll = true
|
||||||
location=["Top"]
|
location = ["Top"]
|
||||||
lines=1
|
lines = 1
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
image_size=64
|
image_size = 64
|
||||||
columns=6
|
columns = 6
|
||||||
orientation="Vertical"
|
orientation = "Vertical"
|
||||||
row_box_orientation="Vertical"
|
row_box_orientation = "Vertical"
|
||||||
content_halign="Center"
|
content_halign = "Center"
|
||||||
height="70%"
|
height = "70%"
|
||||||
width="60%"
|
width = "60%"
|
||||||
valign="Start"
|
valign = "Start"
|
||||||
emoji_hide_label=true
|
emoji_hide_label = true
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
image_size=64
|
image_size = 64
|
||||||
columns=4
|
columns = 4
|
||||||
orientation="Vertical"
|
orientation = "Vertical"
|
||||||
row_box_orientation="Vertical"
|
row_box_orientation = "Vertical"
|
||||||
content_halign="Center"
|
content_halign = "Center"
|
||||||
height="105%"
|
height = "105%"
|
||||||
width="100%"
|
width = "100%"
|
||||||
valign="Start"
|
valign = "Start"
|
||||||
blurred_background=true
|
blurred_background = true
|
||||||
line_max_chars=32
|
line_max_chars = 32
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
image_size=28
|
image_size = 28
|
||||||
allow_images=false
|
allow_images = false
|
||||||
term="kitty -e"
|
term = "kitty -e"
|
||||||
insensitive=true
|
insensitive = true
|
||||||
key_detection_type="Code"
|
key_detection_type = "Code"
|
||||||
blurred_background=false
|
blurred_background = false
|
||||||
location=["Top"]
|
location = ["Top"]
|
||||||
lines=3
|
lines = 3
|
||||||
matching="None"
|
matching = "None"
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
image_size=48
|
image_size = 48
|
||||||
columns=1
|
columns = 1
|
||||||
height="60%"
|
height = "60%"
|
||||||
width="70%"
|
width = "70%"
|
||||||
valign="Start"
|
valign = "Start"
|
||||||
|
|
|
@ -50,6 +50,6 @@ rayon = "1.10.0"
|
||||||
nix = { version = "0.30.0", features = ["process"] }
|
nix = { version = "0.30.0", features = ["process"] }
|
||||||
emoji = "0.2.1"
|
emoji = "0.2.1"
|
||||||
wl-clipboard-rs = "0.9.2"
|
wl-clipboard-rs = "0.9.2"
|
||||||
notify-rust="4.11.7"
|
notify-rust = "4.11.7"
|
||||||
thiserror = "2.0.12"
|
thiserror = "2.0.12"
|
||||||
urlencoding = "2.1.3"
|
urlencoding = "2.1.3"
|
||||||
|
|
|
@ -1,8 +1,7 @@
|
||||||
use std::{env, fs, path::PathBuf, str::FromStr};
|
use std::{env, fs, path::PathBuf, str::FromStr};
|
||||||
|
|
||||||
use clap::{Parser, ValueEnum};
|
use clap::{Parser, ValueEnum};
|
||||||
use serde::de::DeserializeOwned;
|
use serde::{Deserialize, Serialize, de::DeserializeOwned};
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
|
|
||||||
use crate::Error;
|
use crate::Error;
|
||||||
|
@ -462,7 +461,9 @@ pub struct Config {
|
||||||
/// set where the window is displayed.
|
/// set where the window is displayed.
|
||||||
/// can be used to anchor a window to an edge by
|
/// can be used to anchor a window to an edge by
|
||||||
/// setting top,left for example
|
/// 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>>,
|
location: Option<Vec<Anchor>>,
|
||||||
|
|
||||||
|
@ -1050,10 +1051,10 @@ pub fn expand_path(input: &str) -> PathBuf {
|
||||||
let mut path = input.to_string();
|
let mut path = input.to_string();
|
||||||
|
|
||||||
// Expand ~ to home directory
|
// Expand ~ to home directory
|
||||||
if path.starts_with('~') {
|
if path.starts_with('~')
|
||||||
if let Some(home_dir) = dirs::home_dir() {
|
&& let Some(home_dir) = dirs::home_dir()
|
||||||
path = path.replacen('~', home_dir.to_str().unwrap_or(""), 1);
|
{
|
||||||
}
|
path = path.replacen('~', home_dir.to_str().unwrap_or(""), 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Expand $VAR style environment variables
|
// Expand $VAR style environment variables
|
||||||
|
|
|
@ -1277,21 +1277,21 @@ where
|
||||||
|
|
||||||
drop(menu_rows);
|
drop(menu_rows);
|
||||||
|
|
||||||
if let Some(item) = item {
|
if let Some(item) = item
|
||||||
if let Err(e) = handle_selected_item(ui, meta, None, Some(item), None) {
|
&& let Err(e) = handle_selected_item(ui, meta, None, Some(item), None)
|
||||||
log::error!("failed to handle selected item {e}");
|
{
|
||||||
}
|
log::error!("failed to handle selected item {e}");
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
drop(menu_rows);
|
drop(menu_rows);
|
||||||
}
|
}
|
||||||
|
|
||||||
if meta.config.read().unwrap().dynamic_lines() {
|
if meta.config.read().unwrap().dynamic_lines()
|
||||||
if let Some(geometry) = get_monitor_geometry(ui.window.surface().as_ref()) {
|
&& let Some(geometry) = get_monitor_geometry(ui.window.surface().as_ref())
|
||||||
let height =
|
{
|
||||||
calculate_dynamic_lines_window_height(&meta.config.read().unwrap(), ui, geometry);
|
let height =
|
||||||
ui.window.set_height_request(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
|
where
|
||||||
T: Clone + Send + 'static,
|
T: Clone + Send + 'static,
|
||||||
{
|
{
|
||||||
if let Some(fb) = ui.main_box.selected_children().first() {
|
if let Some(fb) = ui.main_box.selected_children().first()
|
||||||
if let Some(child) = fb.child() {
|
&& let Some(child) = fb.child()
|
||||||
let expander = child.downcast::<Expander>().ok();
|
{
|
||||||
if let Some(expander) = expander {
|
let expander = child.downcast::<Expander>().ok();
|
||||||
expander.set_expanded(true);
|
if let Some(expander) = expander {
|
||||||
} else {
|
expander.set_expanded(true);
|
||||||
let data = {
|
} else {
|
||||||
let lock = ui.menu_rows.read().unwrap();
|
let data = {
|
||||||
let menu_item = lock.get(fb);
|
let lock = ui.menu_rows.read().unwrap();
|
||||||
menu_item.map(|menu_item| {
|
let menu_item = lock.get(fb);
|
||||||
(
|
menu_item.map(|menu_item| {
|
||||||
meta.item_provider
|
(
|
||||||
.lock()
|
meta.item_provider
|
||||||
.unwrap()
|
.lock()
|
||||||
.get_sub_elements(menu_item),
|
.unwrap()
|
||||||
menu_item.clone(),
|
.get_sub_elements(menu_item),
|
||||||
)
|
menu_item.clone(),
|
||||||
})
|
)
|
||||||
};
|
})
|
||||||
|
};
|
||||||
|
|
||||||
if let Some((provider_data, menu_item)) = data {
|
if let Some((provider_data, menu_item)) = data {
|
||||||
if let Some(items) = provider_data.items {
|
if let Some(items) = provider_data.items {
|
||||||
build_ui_from_menu_items(ui, meta, items);
|
build_ui_from_menu_items(ui, meta, items);
|
||||||
let query = match meta.expand_mode {
|
let query = match meta.expand_mode {
|
||||||
ExpandMode::Verbatim => menu_item.label.clone(),
|
ExpandMode::Verbatim => menu_item.label.clone(),
|
||||||
ExpandMode::WithSpace => format!("{} ", menu_item.label.clone()),
|
ExpandMode::WithSpace => format!("{} ", menu_item.label.clone()),
|
||||||
};
|
};
|
||||||
|
|
||||||
set_search_text(ui, meta, &query);
|
set_search_text(ui, meta, &query);
|
||||||
if let Ok(new_pos) = i32::try_from(query.len() + 1) {
|
if let Ok(new_pos) = i32::try_from(query.len() + 1) {
|
||||||
ui.search.set_position(new_pos);
|
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}");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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
|
where
|
||||||
T: Clone + Send + 'static,
|
T: Clone + Send + 'static,
|
||||||
{
|
{
|
||||||
if let Some(item) = get_selected_item(ui) {
|
if let Some(item) = get_selected_item(ui)
|
||||||
if let Some(action) = item.action {
|
&& let Some(action) = item.action
|
||||||
if let Err(e) = desktop::copy_to_clipboard(action, None) {
|
&& let Err(e) = desktop::copy_to_clipboard(action, None)
|
||||||
log::error!("failed to copy to clipboard: {e}");
|
{
|
||||||
}
|
log::error!("failed to copy to clipboard: {e}");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if let Err(e) = meta.selected_sender.send(Err(Error::NoSelection)) {
|
if let Err(e) = meta.selected_sender.send(Err(Error::NoSelection)) {
|
||||||
log::error!("failed to send message {e}");
|
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;
|
return;
|
||||||
};
|
};
|
||||||
|
|
||||||
if !config.blurred_background_fullscreen() {
|
if !config.blurred_background_fullscreen()
|
||||||
if let Some(background) = &ui.background {
|
&& let Some(background) = &ui.background
|
||||||
background.set_height_request(geometry.height());
|
{
|
||||||
background.set_width_request(geometry.width());
|
background.set_height_request(geometry.height());
|
||||||
}
|
background.set_width_request(geometry.width());
|
||||||
}
|
}
|
||||||
|
|
||||||
// Calculate target width from config, return early if not set
|
// Calculate target width from config, return early if not set
|
||||||
|
@ -1541,7 +1538,8 @@ fn calculate_row_height<T: Clone + 'static>(
|
||||||
};
|
};
|
||||||
|
|
||||||
log::debug!(
|
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
|
height_box
|
||||||
|
@ -1574,10 +1572,10 @@ where
|
||||||
if let Some(s) = ui.main_box.selected_children().into_iter().next() {
|
if let Some(s) = ui.main_box.selected_children().into_iter().next() {
|
||||||
let list_items = ui.menu_rows.read().unwrap();
|
let list_items = ui.menu_rows.read().unwrap();
|
||||||
let item = list_items.get(&s);
|
let item = list_items.get(&s);
|
||||||
if let Some(selected_item) = item {
|
if let Some(selected_item) = item
|
||||||
if selected_item.visible {
|
&& selected_item.visible
|
||||||
return Some(selected_item.clone());
|
{
|
||||||
}
|
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);
|
label.set_max_width_chars(max_width_chars);
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Some(max_len) = meta.config.read().unwrap().line_max_chars() {
|
if let Some(max_len) = meta.config.read().unwrap().line_max_chars()
|
||||||
if let Some(text) = label_text.as_ref() {
|
&& let Some(text) = label_text.as_ref()
|
||||||
if text.chars().count() > max_len {
|
&& text.chars().count() > max_len
|
||||||
let end = text
|
{
|
||||||
.char_indices()
|
let end = text
|
||||||
.nth(max_len)
|
.char_indices()
|
||||||
.map_or(text.len(), |(idx, _)| idx);
|
.nth(max_len)
|
||||||
label.set_text(&format!("{}...", &text[..end]));
|
.map_or(text.len(), |(idx, _)| idx);
|
||||||
}
|
label.set_text(&format!("{}...", &text[..end]));
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
row_box.append(&label);
|
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| {
|
click.connect_pressed(move |_gesture, n_press, _x, _y| {
|
||||||
if n_press == presses {
|
if n_press == presses
|
||||||
if let Err(e) = handle_selected_item(
|
&& let Err(e) = handle_selected_item(
|
||||||
&click_ui,
|
&click_ui,
|
||||||
&click_meta,
|
&click_meta,
|
||||||
None,
|
None,
|
||||||
Some(element_clone.clone()),
|
Some(element_clone.clone()),
|
||||||
None,
|
None,
|
||||||
) {
|
)
|
||||||
log::error!("{e}");
|
{
|
||||||
}
|
log::error!("{e}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
row.add_controller(click);
|
row.add_controller(click);
|
||||||
|
@ -1963,10 +1960,10 @@ fn find_visible_child<T: Clone>(
|
||||||
|
|
||||||
for i in range {
|
for i in range {
|
||||||
let i_32 = i.try_into().unwrap_or(i32::MAX);
|
let i_32 = i.try_into().unwrap_or(i32::MAX);
|
||||||
if let Some(child) = flow_box.child_at_index(i_32) {
|
if let Some(child) = flow_box.child_at_index(i_32)
|
||||||
if child.is_visible() {
|
&& child.is_visible()
|
||||||
return Some(child);
|
{
|
||||||
}
|
return Some(child);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -60,10 +60,10 @@ impl AutoItemProvider {
|
||||||
.is_some_and(|t| t != &AutoRunType::Auto)
|
.is_some_and(|t| t != &AutoRunType::Auto)
|
||||||
{
|
{
|
||||||
let mut data = self.drun.get_elements(None);
|
let mut data = self.drun.get_elements(None);
|
||||||
if let Some(items) = data.items.as_mut() {
|
if let Some(items) = data.items.as_mut()
|
||||||
if let Some(mut ssh) = self.ssh.get_elements(None).items {
|
&& let Some(mut ssh) = self.ssh.get_elements(None).items
|
||||||
items.append(&mut ssh);
|
{
|
||||||
}
|
items.append(&mut ssh);
|
||||||
}
|
}
|
||||||
|
|
||||||
self.last_mode = Some(AutoRunType::Auto);
|
self.last_mode = Some(AutoRunType::Auto);
|
||||||
|
@ -77,7 +77,18 @@ impl AutoItemProvider {
|
||||||
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
fn contains_math_functions_or_starts_with_number(input: &str) -> bool {
|
||||||
// Regex for function names (word boundaries to match whole words)
|
// Regex for function names (word boundaries to match whole words)
|
||||||
static MATH_REGEX: LazyLock<Regex> = LazyLock::new(|| {
|
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)
|
// Regex for strings that start with a number (including decimals)
|
||||||
|
|
|
@ -7,7 +7,6 @@ use std::{
|
||||||
|
|
||||||
use freedesktop_file_parser::EntryType;
|
use freedesktop_file_parser::EntryType;
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
Error,
|
Error,
|
||||||
|
@ -20,12 +19,6 @@ use crate::{
|
||||||
modes::load_cache,
|
modes::load_cache,
|
||||||
};
|
};
|
||||||
|
|
||||||
#[derive(Debug, Deserialize, Serialize, Clone)]
|
|
||||||
struct DRunCache {
|
|
||||||
desktop_entry: String,
|
|
||||||
run_count: usize,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Clone)]
|
#[derive(Clone)]
|
||||||
pub(crate) struct DRunProvider<T: Clone> {
|
pub(crate) struct DRunProvider<T: Clone> {
|
||||||
items: Option<Vec<MenuItem<T>>>,
|
items: Option<Vec<MenuItem<T>>>,
|
||||||
|
@ -78,8 +71,7 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
||||||
let entries: Vec<MenuItem<T>> = find_desktop_files()
|
let entries: Vec<MenuItem<T>> = find_desktop_files()
|
||||||
.into_par_iter()
|
.into_par_iter()
|
||||||
.filter(|file| {
|
.filter(|file| {
|
||||||
!file.entry.no_display.unwrap_or(false)
|
!file.entry.no_display.unwrap_or(false) && !file.entry.hidden.unwrap_or(false)
|
||||||
&& !file.entry.hidden.unwrap_or(false)
|
|
||||||
})
|
})
|
||||||
.filter_map(|file| {
|
.filter_map(|file| {
|
||||||
let name = lookup_name_with_locale(
|
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 {
|
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,
|
_ => return None,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -104,7 +100,10 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
||||||
.unwrap_or(false);
|
.unwrap_or(false);
|
||||||
|
|
||||||
if !cmd_exists {
|
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;
|
return None;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -142,8 +141,8 @@ impl<T: Clone + Send + Sync> DRunProvider<T> {
|
||||||
.or(icon.clone())
|
.or(icon.clone())
|
||||||
.unwrap_or("application-x-executable".to_string());
|
.unwrap_or("application-x-executable".to_string());
|
||||||
|
|
||||||
|
let action =
|
||||||
let action = self.get_action(in_terminal, action.exec.clone(), &action_name);
|
self.get_action(in_terminal, action.exec.clone(), &action_name);
|
||||||
|
|
||||||
entry.sub_elements.push(MenuItem::new(
|
entry.sub_elements.push(MenuItem::new(
|
||||||
action_name,
|
action_name,
|
||||||
|
|
|
@ -137,12 +137,11 @@ impl<T: Clone> ItemProvider<T> for FileItemProvider<T> {
|
||||||
if let Some(mut path_str) =
|
if let Some(mut path_str) =
|
||||||
entry.path().to_str().map(std::string::ToString::to_string)
|
entry.path().to_str().map(std::string::ToString::to_string)
|
||||||
{
|
{
|
||||||
if trimmed_search.starts_with('~') {
|
if trimmed_search.starts_with('~')
|
||||||
if let Some(home_dir) = dirs::home_dir() {
|
&& let Some(home_dir) = dirs::home_dir()
|
||||||
if let Some(home_str) = home_dir.to_str() {
|
&& let Some(home_str) = home_dir.to_str()
|
||||||
path_str = path_str.replace(home_str, "~");
|
{
|
||||||
}
|
path_str = path_str.replace(home_str, "~");
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if entry.path().is_dir() {
|
if entry.path().is_dir() {
|
||||||
|
|
|
@ -162,7 +162,8 @@ fn tokenize(expr: &str) -> Result<VecDeque<Token>, String> {
|
||||||
i += 1;
|
i += 1;
|
||||||
}
|
}
|
||||||
'0'..='9' | '.' => {
|
'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(')')) = last_token {
|
||||||
if let Some(Token::Op(op)) = tokens.back() {
|
if let Some(Token::Op(op)) = tokens.back() {
|
||||||
if *op == ')' {
|
if *op == ')' {
|
||||||
|
|
Loading…
Add table
Reference in a new issue