Wrap LoadedRuntime._library in ManuallyDrop so dlclose() is never called.
dlclose() unmaps the library code; thread-local destructors inside liblua.so
then SIGSEGV when they try to run against the unmapped addresses.
Also filter out non-.lua plugins in the Lua runtime's discover_plugins()
so liblua.so does not attempt to load Rune plugins.
- owlry-core/manifest: add entry_point alias for entry field, add ProviderSpec
struct for [[providers]] array, change default entry to main.lua
- owlry-lua/manifest: add ProviderDecl struct and providers: Vec<ProviderDecl>
for [[providers]] support
- owlry-lua/loader: fall back to manifest [[providers]] when script has no API
registrations; fall back to global refresh() for manifest-declared providers
- owlry-lua/api: expose call_global_refresh() that calls the top-level Lua
refresh() function directly
- owlry/plugin_commands: update create templates to emit new format:
entry_point instead of entry, [[providers]] instead of [provides],
main.rn/main.lua instead of init.rn/init.lua, Rune uses Item::new() builder
pattern, Lua uses standalone refresh() function
- cmd_validate: accept [[providers]] declarations as a valid provides source
- Config::save() now merges into existing file via toml_edit to preserve
user comments and unknown keys instead of overwriting
- Remove 16 dead ProvidersConfig plugin-toggle fields (uuctl, ssh, clipboard,
bookmarks, emoji, scripts, files, media, weather_*, pomodoro_*) that became
unreachable after accept_all=true was introduced
- Wire general.tabs to ProviderFilter::new() to drive UI tab display
- Fix set_single_mode() and toggle() not clearing accept_all, making tab
filtering a no-op in default launch mode
- Add restore_all_mode() for cycle-back-to-All path in tab cycling
- Reduce PROVIDER_TOGGLES to built-in providers only
reqwest 0.13 defaults to rustls -> aws-lc-rs which requires cmake/nasm
in minimal build environments (AUR chroot). Switch all direct reqwest
users to native-tls (system OpenSSL) to fix clean chroot build failures
reported by users.
Affected crates: owlry-core, owlry-lua, owlry-rune
PKGBUILD: add openssl to depends for all three runtime packages
Also add scripts/aur-local-test for clean chroot testing workflow
Merge four separate prefix arrays (core full, plugin full, core
partial, plugin partial) into two arrays with a single loop each
that checks both full and partial match. Halves the data and
eliminates the duplicate iteration.
Replace while-contains-replace loop with a single-pass char
iterator. Eliminates O(n²) behavior and repeated allocations
on pathological desktop file Exec values.
record_launch no longer calls save() synchronously. The dirty flag
is set and the Drop impl flushes on shutdown. Removes a JSON
serialize + fs::write from the hot launch path.
Refactor search_with_frecency to score static provider items by
reference (&LaunchItem, i64) instead of cloning every match.
Use select_nth_unstable_by for O(n) partial sort, then clone
only the max_results survivors. Reduces clones from O(total_matches)
to O(max_results) — typically from hundreds to ~15.
Replace RwLock<Vec<LaunchItem>> with plain Vec. The inner RwLock
was unnecessary — refresh() takes &mut self (exclusive access
guaranteed by the outer Arc<RwLock<ProviderManager>>). The unsafe
block in items() dropped the RwLockReadGuard while returning a
slice backed by the raw pointer, creating a dangling reference.
:config and :conv were not in the prefix lists, so typing them
showed 'Plugin' mode but didn't route to the config/converter
providers. Also added :settings, :converter aliases.
Register ConfigProvider as built-in dynamic provider. Extend
execute_plugin_action to dispatch CONFIG:* commands via the
DynamicProvider::execute_action trait method.
Calculator and converter registered as built-in dynamic providers.
System registered as built-in static provider. All gated by config
toggles (calculator, converter, system — default true).
Foundation for built-in calculator, converter, and system providers.
DynamicProvider trait for per-keystroke providers. ProviderManager
iterates builtin_dynamic alongside native dynamic plugins in search.
The 5-second timer emitted 'changed' on the search entry in daemon
mode, triggering a full re-query that rebuilt the result list and
selected row 0 — jumping the user back to the top while browsing.
Widget refresh is a daemon-side concern; the UI gets updated data
on the next user-initiated search. Only keep the timer for local
(dmenu) mode where the UI owns the providers directly.
Calculator and converter results now get a 10k grouping bonus so all
their results stay together above websearch/filesearch. Previously
websearch (priority 9000) would interleave with converter results
(9000, 8999, 8998...) since they had the same base priority.
Websearch is a generic fallback — it always shows a result, so
highlighting it adds no signal. Filesearch returns fuzzy matches,
not auto-detected conversions. Only calc and conv produce direct
answers that deserve highlighting.
Highlighting:
- Dynamic plugin results (calculator, converter, websearch, filesearch)
get a subtle accent left-border + background tint when auto-detected
- Exact name matches (case-insensitive) are highlighted the same way
- Exact match on apps gets a higher score boost (50k) than other
providers (30k), so apps rank first when names match exactly
Shadow:
- Removed hardcoded box-shadow from all theme CSS files
- Added --owlry-shadow variable in base.css (defaults to none)
- Themes can opt into shadow via --owlry-shadow if desired
CSS class: .owlry-result-highlight on ResultRow