aboutsummaryrefslogtreecommitdiff
path: root/.config/awesome/ui/fresnel
diff options
context:
space:
mode:
authordelta <darkussdelta@gmail.com>2023-03-04 22:04:55 +0100
committerdelta <darkussdelta@gmail.com>2023-03-04 22:18:21 +0100
commitf0b32f45746c026d402651013b7e98315d6956a1 (patch)
treef42609e98522da081cebdd21a674a702d1054bbc /.config/awesome/ui/fresnel
parenta0f8b5fa6acdd1c2477fb1881dd9067956bf0ae6 (diff)
restructure awesome config, add fresnel
Diffstat (limited to '.config/awesome/ui/fresnel')
-rw-r--r--.config/awesome/ui/fresnel/init.lua276
-rw-r--r--.config/awesome/ui/fresnel/lenses/.gitignore2
-rw-r--r--.config/awesome/ui/fresnel/lenses/Cargo.toml18
-rw-r--r--.config/awesome/ui/fresnel/lenses/install.log10
l---------.config/awesome/ui/fresnel/lenses/liblenses.so1
-rw-r--r--.config/awesome/ui/fresnel/lenses/rustfmt.toml3
-rw-r--r--.config/awesome/ui/fresnel/lenses/src/application.rs107
-rw-r--r--.config/awesome/ui/fresnel/lenses/src/calculator.rs25
-rw-r--r--.config/awesome/ui/fresnel/lenses/src/entry.rs20
-rw-r--r--.config/awesome/ui/fresnel/lenses/src/lib.rs16
10 files changed, 478 insertions, 0 deletions
diff --git a/.config/awesome/ui/fresnel/init.lua b/.config/awesome/ui/fresnel/init.lua
new file mode 100644
index 0000000..cf1357a
--- /dev/null
+++ b/.config/awesome/ui/fresnel/init.lua
@@ -0,0 +1,276 @@
+local awful = require "awful"
+local gtable = require "gears.table"
+local gdebug = require "gears.debug"
+local gfs = require "gears.filesystem"
+local h = require "misc.helpers"
+local cfg = require "misc.cfg"
+local vars = require "misc.vars"
+local wibox = require "wibox"
+local beautiful = require "beautiful"
+local rubato = require "lib.rubato"
+local al_prompt = require "lib.bling.widget.app_launcher.prompt"
+local btn = awful.button.names
+
+package.cpath = package.cpath .. ";" .. gfs.get_configuration_dir() .. "ui/fresnel/lenses/target/debug/lib?.so"
+
+local lenses = require "lenses"
+local max_entries = 10
+
+local fresnel = {}
+
+fresnel._toggled = false
+fresnel._entries_exec = {}
+fresnel._entries_offset = 0
+fresnel._entries_count = 0
+fresnel._visible_entries = 0
+fresnel._selected_index = 1
+
+function fresnel:_exec_entry(entry_index)
+ local exec = self._entries_exec[entry_index]
+ if type(exec) ~= "userdata" then
+ awful.spawn((exec[2] and cfg.terminal .. " -e " or "") .. exec[1])
+ end
+end
+
+function fresnel:_update(query, scrolled)
+ query = query or ""
+ scrolled = scrolled or false
+
+ if not scrolled then
+ self._selected_index = 1
+ self._entries_offset = 0
+ end
+
+ local layout = self._widget.widget:get_children_by_id("entry_layout")[1]
+ local status = self._widget.widget:get_children_by_id("status")[1]
+ local all_providers = {}
+ local entries_count = 0
+
+ self._entries_exec = {}
+ layout:reset()
+
+ for _, provider in h.opairs(lenses) do
+ local entries = provider(query)
+
+ table.sort(entries, function(a, b)
+ return a.message < b.message
+ end)
+
+ all_providers = gtable.join(all_providers, entries)
+ end
+
+ self._entries_count = #all_providers
+
+ for i, entry in ipairs(all_providers) do
+ if i <= self._entries_offset then
+ goto continue
+ end
+ if entries_count == max_entries then break end
+ table.insert(self._entries_exec, entry.exec)
+
+ local entry_widget = wibox.widget {
+ widget = wibox.container.background,
+ shape = vars.shape,
+ {
+ widget = wibox.container.margin,
+ margins = vars.padding,
+ {
+ widget = wibox.container.constraint,
+ strategy = "max",
+ height = vars.char_height,
+ {
+ {
+ widget = wibox.container.background,
+ fg = vars.colors.dim.fg,
+ {
+ widget = wibox.widget.textbox,
+ text = entry.provider .. " | "
+ }
+ },
+ {
+ widget = wibox.widget.textbox,
+ text = entry.message
+ },
+ spacing = vars.padding,
+ layout = wibox.layout.fixed.horizontal
+ }
+ }
+ },
+ buttons = {
+ awful.button {
+ modifiers = {},
+ button = btn.LEFT,
+ on_press = function()
+ self:_exec_entry(i)
+ end
+ }
+ },
+ _selected = false
+ }
+
+ if self._selected_index + self._entries_offset == i then
+ entry_widget._selected = true
+ entry_widget.bg = vars.colors.black
+ end
+
+ entry_widget:connect_signal("mouse::enter", function()
+ if entry_widget._selected == true then return end
+ entry_widget.bg = vars.colors.black
+ end)
+
+ entry_widget:connect_signal("mouse::leave", function()
+ if entry_widget._selected == true then return end
+ entry_widget.bg = vars.colors.bg
+ end)
+
+ layout:add(entry_widget)
+
+ entries_count = entries_count + 1
+ self._visible_entries = entries_count
+ ::continue::
+ end
+
+ status.text = self._entries_offset + self._selected_index .. "/" .. self._entries_count
+end
+
+fresnel._text = ""
+fresnel._prompt = al_prompt {
+ prompt = "",
+ reset_on_stop = true,
+ ul_cursor = "low",
+ bg_cursor = vars.colors.black,
+ changed_callback = function(text)
+ if fresnel._text == text then return end
+ if fresnel._toggled == false then return end
+ fresnel:_update(text)
+ fresnel._text = text
+ end,
+ keypressed_callback = function(mod, key)
+ if key == "Escape" or key == " " and mod.Mod4 then
+ fresnel:hide()
+ elseif key == "Return" then
+ fresnel:_exec_entry(fresnel._selected_index)
+ fresnel:hide()
+ elseif key == "Up" then
+ local next_index = fresnel._selected_index - 1
+ if next_index < 1 and fresnel._entries_offset == 0 then
+ return
+ elseif next_index < 1 and fresnel._entries_offset > 0 then
+ fresnel._entries_offset = fresnel._entries_offset - 1
+ else
+ fresnel._selected_index = next_index
+ end
+
+ fresnel:_update(fresnel._text, true)
+ elseif key == "Down" then
+ local next_index = fresnel._selected_index + 1
+ if next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries == fresnel._entries_count then
+ return
+ elseif next_index > fresnel._visible_entries and fresnel._entries_offset + fresnel._visible_entries < fresnel._entries_count then
+ fresnel._entries_offset = fresnel._entries_offset + 1
+ else
+ fresnel._selected_index = next_index
+ end
+
+ fresnel:_update(fresnel._text, true)
+ end
+ end
+}
+
+fresnel._widget = h.popup {
+ visible = false,
+ ontop = true,
+ placement = function(d)
+ awful.placement.top(d, {
+ margins = {
+ top = beautiful.useless_gap * 2
+ }
+ })
+ end,
+ minimum_width = screen[1].geometry.width / 2,
+ maximum_width = screen[1].geometry.width / 2,
+ widget = {
+ {
+ widget = wibox.container.background,
+ bg = vars.colors.black,
+ fg = vars.colors.dim.fg,
+ shape = vars.shape,
+ {
+ widget = wibox.container.margin,
+ margins = vars.padding,
+ {
+ {
+ widget = wibox.widget.textbox,
+ text = ">"
+ },
+ {
+ widget = wibox.container.margin,
+ margins = {
+ left = vars.padding,
+ right = vars.padding
+ },
+ {
+ widget = wibox.container.constraint,
+ strategy = "max",
+ height = vars.char_height,
+ {
+ widget = wibox.container.background,
+ fg = vars.colors.fg,
+ fresnel._prompt.textbox
+ }
+ }
+ },
+ {
+ widget = wibox.widget.textbox,
+ text = "0/0",
+ id = "status"
+ },
+ layout = wibox.layout.align.horizontal
+ }
+ }
+ },
+ {
+ widget = wibox.container.margin,
+ margins = {
+ top = vars.padding
+ },
+ {
+ spacing = vars.padding,
+ layout = wibox.layout.fixed.vertical,
+ id = "entry_layout"
+ }
+ },
+ layout = wibox.layout.align.vertical
+ }
+}
+fresnel._widget.maximum_height = vars.big_padding * 2 + (vars.padding * 2 + vars.char_height) * (1 + 10) + vars.padding + vars.padding * 9
+
+function fresnel:show()
+ self._toggled = true
+ self._timed.target = 1
+ self:_update()
+ self._prompt:start()
+end
+
+function fresnel:hide()
+ self._toggled = false
+ self._timed.target = 0
+ self._prompt:stop()
+end
+
+fresnel._timed = rubato.timed {
+ duration = vars.anim_duration,
+ intro = vars.anim_intro,
+ pos = 0,
+ subscribed = function(pos)
+ fresnel._widget.opacity = pos
+
+ if pos == 0 then
+ fresnel._widget.visible = false
+ else
+ fresnel._widget.visible = true
+ end
+ end
+}
+
+return fresnel
diff --git a/.config/awesome/ui/fresnel/lenses/.gitignore b/.config/awesome/ui/fresnel/lenses/.gitignore
new file mode 100644
index 0000000..4fffb2f
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/.gitignore
@@ -0,0 +1,2 @@
+/target
+/Cargo.lock
diff --git a/.config/awesome/ui/fresnel/lenses/Cargo.toml b/.config/awesome/ui/fresnel/lenses/Cargo.toml
new file mode 100644
index 0000000..4dcb8bc
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/Cargo.toml
@@ -0,0 +1,18 @@
+[package]
+name = "lenses"
+version = "0.1.0"
+edition = "2021"
+
+# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
+
+[dependencies]
+freedesktop_entry_parser = "1.3.0"
+meval = "0.2.0"
+mlua = { version = "0.8.7", features = [ "module", "lua54", "serialize" ] }
+parking_lot = "0.12.1"
+rayon = "1.6.1"
+serde = { version = "1.0.152", features = [ "derive" ] }
+url = "2.3.1"
+
+[lib]
+crate-type = ["cdylib"]
diff --git a/.config/awesome/ui/fresnel/lenses/install.log b/.config/awesome/ui/fresnel/lenses/install.log
new file mode 100644
index 0000000..c0f5d63
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/install.log
@@ -0,0 +1,10 @@
+[03:45:24 2023-02-24] FETCHING Version 2.16.1
+[03:45:24 2023-02-24] CREATING /home/delta/.spicetify
+[03:45:24 2023-02-24] DOWNLOADING https://github.com/spicetify/spicetify-cli/releases/download/v2.16.1/spicetify-2.16.1-linux-amd64.tar.gz
+[03:45:34 2023-02-24] EXTRACTING /home/delta/.spicetify/spicetify.tar.gz
+[03:45:34 2023-02-24] SETTING EXECUTABLE PERMISSIONS TO /home/delta/.spicetify/spicetify
+[03:45:34 2023-02-24] REMOVING /home/delta/.spicetify/spicetify.tar.gz
+[03:45:34 2023-02-24] APPENDING /home/delta/.spicetify to PATH in /home/delta/.config/fish/config.fish
+[03:45:34 2023-02-24] Restart your shell to have spicetify in your PATH.
+[03:45:34 2023-02-24] spicetify v2.16.1 was installed successfully to /home/delta/.spicetify
+[03:45:34 2023-02-24] Run 'spicetify --help' to get started
diff --git a/.config/awesome/ui/fresnel/lenses/liblenses.so b/.config/awesome/ui/fresnel/lenses/liblenses.so
new file mode 120000
index 0000000..5f7fc45
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/liblenses.so
@@ -0,0 +1 @@
+target/liblenses.so \ No newline at end of file
diff --git a/.config/awesome/ui/fresnel/lenses/rustfmt.toml b/.config/awesome/ui/fresnel/lenses/rustfmt.toml
new file mode 100644
index 0000000..36afbbd
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/rustfmt.toml
@@ -0,0 +1,3 @@
+imports_layout = "Vertical"
+unstable_features = true
+group_imports = "StdExternalCrate"
diff --git a/.config/awesome/ui/fresnel/lenses/src/application.rs b/.config/awesome/ui/fresnel/lenses/src/application.rs
new file mode 100644
index 0000000..0cf6c1a
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/src/application.rs
@@ -0,0 +1,107 @@
+use std::{
+ fs::read_dir,
+ path::PathBuf,
+};
+
+use freedesktop_entry_parser as fd;
+use mlua::prelude::*;
+use parking_lot::Mutex;
+use rayon::prelude::*;
+use url::Url;
+
+use crate::entry::{
+ entries_to_lua_table,
+ Entry,
+};
+
+fn parse_entry<'a>(entry: fd::Entry, path: PathBuf) -> Result<Entry, ()> {
+ let section = entry.section("Desktop Entry");
+ let name = section.attr("Name").ok_or(())?.to_string();
+
+ if section.attr("Type").ok_or(())? != "Application" {
+ return Err(());
+ }
+
+ match section.attr("OnlyShowIn") {
+ Some(_) => return Err(()),
+ None => {}
+ }
+
+ match section.attr("Hidden") {
+ Some(_) => return Err(()),
+ None => {}
+ }
+
+ match section.attr("NoDisplay") {
+ Some(_) => return Err(()),
+ None => {}
+ }
+
+ let exec = section.attr("Exec").ok_or(())?.to_string();
+ let mut new_exec = exec.clone();
+ for (index, _) in exec.match_indices("%") {
+ match exec.chars().nth(index + 1).unwrap().to_ascii_lowercase() {
+ 'i' => match section.attr("Icon") {
+ Some(icon) => new_exec.replace_range(index..index + 2, &format!("--icon {}", icon)),
+ None => {}
+ },
+ 'c' => new_exec.replace_range(index..index + 2, &name),
+ 'k' => new_exec.replace_range(index..index + 2, Url::from_file_path(&path)?.as_str()),
+
+ 'f' | 'u' | 'v' | 'm' | 'd' | 'n' => new_exec.replace_range(index..index + 2, ""),
+ _ => continue,
+ }
+ }
+
+ Ok(Entry {
+ message: name,
+ exec: Some((
+ new_exec,
+ section
+ .attr("Terminal")
+ .unwrap_or("false")
+ .parse()
+ .map_err(drop)?,
+ )),
+ provider: "Application".to_string(),
+ })
+}
+
+pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
+ let applications_dir = "/usr/share/applications";
+ let entries = read_dir(applications_dir)?
+ .map(|result| result.map(|e| e.path()))
+ .collect::<Result<Vec<_>, std::io::Error>>()?;
+
+ let entries = entries
+ .into_iter()
+ .filter(|e| match e.extension() {
+ Some(ext) if ext == "desktop" => true,
+ None | _ => false,
+ })
+ .collect::<Vec<_>>();
+
+ let mut parsed_entries: Mutex<Vec<Entry>> = Mutex::new(Vec::new());
+
+ entries.into_par_iter().for_each(|path| {
+ let entry = match fd::parse_entry(&path) {
+ Ok(entry) => entry,
+ Err(_) => return,
+ };
+
+ match parse_entry(entry, path) {
+ Ok(parsed_entry) => parsed_entries.lock().push(parsed_entry),
+ Err(_) => return,
+ }
+ });
+
+ Ok(entries_to_lua_table(
+ parsed_entries
+ .get_mut()
+ .iter()
+ .filter(|entry| entry.message.to_lowercase().contains(&input))
+ .map(|entry| (*entry).clone())
+ .collect(),
+ lua,
+ ))
+}
diff --git a/.config/awesome/ui/fresnel/lenses/src/calculator.rs b/.config/awesome/ui/fresnel/lenses/src/calculator.rs
new file mode 100644
index 0000000..792985d
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/src/calculator.rs
@@ -0,0 +1,25 @@
+use meval::eval_str;
+use mlua::prelude::*;
+
+use crate::entry::{
+ entries_to_lua_table,
+ Entry,
+};
+
+pub fn query(lua: &Lua, input: String) -> LuaResult<LuaTable> {
+ println!("{:?}", input);
+ let result = match eval_str(input.trim()) {
+ Ok(ok) => ok.to_string(),
+ Err(_) => return Ok(lua.create_table()?),
+ };
+
+ Ok(entries_to_lua_table(
+ vec![Entry {
+ message: result,
+ exec: None,
+ // icon: '',
+ provider: "Calculator".to_string(),
+ }],
+ lua,
+ ))
+}
diff --git a/.config/awesome/ui/fresnel/lenses/src/entry.rs b/.config/awesome/ui/fresnel/lenses/src/entry.rs
new file mode 100644
index 0000000..d6e7467
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/src/entry.rs
@@ -0,0 +1,20 @@
+use mlua::{
+ prelude::*,
+ LuaSerdeExt,
+};
+use serde::Serialize;
+
+#[derive(Serialize, Clone)]
+pub struct Entry {
+ pub message: String,
+ pub exec: Option<(String, bool)>,
+ // pub icon: char,
+ pub provider: String,
+}
+
+pub fn entries_to_lua_table(entries: Vec<Entry>, lua: &Lua) -> LuaTable {
+ match lua.to_value(&entries).unwrap() {
+ LuaValue::Table(t) => t,
+ _ => unreachable!(),
+ }
+}
diff --git a/.config/awesome/ui/fresnel/lenses/src/lib.rs b/.config/awesome/ui/fresnel/lenses/src/lib.rs
new file mode 100644
index 0000000..e4fc881
--- /dev/null
+++ b/.config/awesome/ui/fresnel/lenses/src/lib.rs
@@ -0,0 +1,16 @@
+mod application;
+mod calculator;
+mod entry;
+
+use mlua::prelude::*;
+
+#[mlua::lua_module]
+fn lenses(lua: &Lua) -> LuaResult<LuaTable> {
+ let exports = lua.create_table()?;
+ // lua.create_fun
+ // exports.push(application::query)?;
+ exports.set("1", lua.create_function(calculator::query)?)?;
+ exports.set("2", lua.create_function(application::query)?)?;
+
+ Ok(exports)
+}