Compare commits

..

1 Commits

Author SHA1 Message Date
imgurbot12
f4bc65e5de chore: include lock for release build 2024-03-28 09:05:28 -07:00
17 changed files with 270 additions and 571 deletions

4
.gitignore vendored
View File

@ -1,4 +1,2 @@
target
# Cargo.lock
result
.idea
Cargo.lock

350
Cargo.lock generated

File diff suppressed because it is too large Load Diff

22
LICENSE
View File

@ -1,22 +0,0 @@
The MIT License (MIT)
Copyright (c) 2024 Andrew Scott
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@ -1,4 +1,5 @@
## RMenu
RMenu
------
<!--
TODO: improve documentation:
@ -10,25 +11,14 @@ Another customizable Application-Launcher written in Rust
### Features
- Blazingly Fast 🔥
- Simple and Easy to Use
- Customizable (Configuration and CSS-Styling)
- Plugin Support
- Dmenu-Like Stdin Menu Generation
* Blazingly Fast 🔥
* Simple and Easy to Use
* Customizable (Configuration and CSS-Styling)
* Plugin Support
* Dmenu-Like Stdin Menu Generation
### Installation
RMenu now has Nix support thanks to
[@LordGrimmauld](https://github.com/LordGrimmauld)!
Install Dependencies (Ubuntu)
```bash
sudo apt install pkg-config libglib2.0-dev libghc-gi-gdk-dev libsoup-3.0-dev libjavascriptcoregtk-4.1-dev libwebkit2gtk-4.1-dev libnm-dev
```
Compile and Install Binaries/Config-Files
```bash
$ make install
```
@ -43,13 +33,13 @@ $ rmenu --help
RMenu Comes with a few default plugins.
| Name | Description |
| Name | Description |
| :-------: | ------------------------------------------------------- |
| run | Execute a program in $PATH |
| drun | Run a Configured Free-Desktop Application |
| audio | Select and Set-Default PulseAudio Sink using `pactl` |
| network | Wi-Fi Login/Connection Tool using Network-Manager |
| window | Simple Window Switcher (Currently Only Support Sway) |
| run | Execute a program in $PATH |
| drun | Run a Configured Free-Desktop Application |
| audio | Select and Set-Default PulseAudio Sink using `pactl` |
| network | Wi-Fi Login/Connection Tool using Network-Manager |
| window | Simple Window Switcher (Currently Only Support Sway) |
| powermenu | Simple Power/Logout Tool (Currently Only Supports Sway) |
Run a plugin by passing the `-r` flag like one of the following:
@ -66,16 +56,16 @@ Or even run plugins in combination if you'd like:
$ rmenu -r run -r drun
```
Custom Menus can also be passed much like Dmenu by passing items via an input.
The schema follows a standard as defined in [rmenu-plugin](./rmenu-plugin)
Custom Menus can also be passed much like Dmenu by passing items via
an input. The schema follows a standard as defined in [rmenu-plugin](./rmenu-plugin)
```bash
$ generate-my-menu.sh > input.json
$ rmenu -i input.json
```
When neither a plugin nor an input are specified, rmenu defaults to reading from
stdin.
When neither a plugin nor an input are specified, rmenu defaults to
reading from stdin.
```bash
$ generate-my-menu.sh | rmenu
@ -83,23 +73,20 @@ $ generate-my-menu.sh | rmenu
### Configuration
Customize RMenu Behavior and Appearal in a
[single config](./rmenu/public/config.yaml)
Customize RMenu Behavior and Appearal in a [single config](./rmenu/public/config.yaml)
Customize the entire app's appearance with CSS. A few
[Example Themes](./themes/) are available as reference. To try them out use:
`rmenu --css <my-css-theme>` or move the css file to
`$HOME/.config/rmenu/style.css`
Customize the entire app's appearance with CSS. A few [Example Themes](./themes/)
are available as reference. To try them out use: `rmenu --css <my-css-theme>`
or move the css file to `$HOME/.config/rmenu/style.css`
### Scripting
RMenu plugins and imports communicate using JSON messages defined in
`rmenu-plugin`. Writing JSON in shell is painful, so rmenu provides another
cli-tool to help build messages quickly and easily while still retaining the
flexibility of JSON.
RMenu plugins and imports communicate using JSON messages defined in `rmenu-plugin`.
Writing JSON in shell is painful, so rmenu provides another cli-tool to help build
messages quickly and easily while still retaining the flexibility of JSON.
After Installing. Use the following command, and look at
[other-plugins](./other-plugins) for example uses.
After Installing. Use the following command, and look at [other-plugins](./other-plugins)
for example uses.
```
$ rmenu-build --help
@ -108,21 +95,16 @@ $ rmenu-build --help
### Example Screenshots
#### Launchpad
![launchpad](./screenshots/launchpad.png)
#### Nord
![nord](./screenshots/nord.png)
#### Dark
![dark](./screenshots/dark.png)
#### Solarized
![solzarized](./screenshots/solarized.png)
#### PowerMenu
![powermenu](./screenshots/powermenu.png)

View File

@ -1,26 +0,0 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1711655175,
"narHash": "sha256-1xiaYhC3ul4y+i3eicYxeERk8ZkrNjLkrFSb/UW36Zw=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "64c81edb4b97a51c5bbc54c191763ac71a6517ee",
"type": "github"
},
"original": {
"id": "nixpkgs",
"ref": "nixpkgs-unstable",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

View File

@ -1,99 +0,0 @@
{
description = "rmenu: Another customizable Application-Launcher written in Rust";
inputs.nixpkgs.url = "nixpkgs/nixpkgs-unstable";
outputs = {
nixpkgs,
self,
...
}: let
systems = [
"x86_64-linux"
"aarch64-linux"
];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
in {
devShells = forAllSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
overrides = (builtins.fromTOML (builtins.readFile ./rust-toolchain.toml));
libPath = with pkgs; lib.makeLibraryPath [
# load external libraries that you need in your rust project here
glib
gtk3
libsoup_3
networkmanager
webkitgtk_4_1
];
in {
default = pkgs.mkShell {
buildInputs = with pkgs; [
llvmPackages.bintools
rustup
];
RUSTC_VERSION = overrides.toolchain.channel;
# https://github.com/rust-lang/rust-bindgen#environment-variables
LIBCLANG_PATH = pkgs.lib.makeLibraryPath [ pkgs.llvmPackages_latest.libclang.lib ];
shellHook = ''
export PATH=$PATH:''${CARGO_HOME:-~/.cargo}/bin
export PATH=$PATH:''${RUSTUP_HOME:-~/.rustup}/toolchains/$RUSTC_VERSION-x86_64-unknown-linux-gnu/bin/
'';
# Add precompiled library to rustc search path
RUSTFLAGS = (builtins.map (a: ''-L ${a}/lib'') [
# add libraries here (e.g. pkgs.libvmi)
]);
LD_LIBRARY_PATH = libPath;
# Add glibc, clang, glib, and other headers to bindgen search path
BINDGEN_EXTRA_CLANG_ARGS =
# Includes normal include path
(builtins.map (a: ''-I"${a}/include"'') [
# add dev libraries here (e.g. pkgs.libvmi.dev)
pkgs.glibc.dev
])
# Includes with special directory paths
++ [
''-I"${pkgs.llvmPackages_latest.libclang.lib}/lib/clang/${pkgs.llvmPackages_latest.libclang.version}/include"''
''-I"${pkgs.glib.dev}/include/glib-2.0"''
''-I${pkgs.glib.out}/lib/glib-2.0/include/''
];
packages = with pkgs; [
# base toolchain
pkg-config
rustup
# runtime deps
glib
gtk3
libsoup_3
networkmanager
webkitgtk_4_1
# nix utils
self.formatter.${pkgs.system}
nil
];
};
});
formatter = forAllSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
in pkgs.alejandra);
packages = forAllSystems (system: let
pkgs = nixpkgs.legacyPackages.${system};
rmenu-pkg = (pkgs.callPackage ./nix/package.nix {});
in {
rmenu = rmenu-pkg;
default = rmenu-pkg;
});
nixosModules = let
rmenu-module = (import ./nix/rmenu.nix);
in {
rmenu = rmenu-module;
default = rmenu-module;
};
};
}

View File

@ -1,91 +0,0 @@
{ cargo
, fetchFromGitHub
, glib
, gnused
, gtk3
, lib
, libsoup_3
, networkmanager
, pkg-config
, rustPlatform
, rustc
, stdenv
, webkitgtk_4_1
, wrapGAppsHook
}:
rustPlatform.buildRustPackage rec {
version = "1.1.0";
pname = "rmenu";
src = lib.cleanSource ../.;
# src = fetchFromGitHub {
# rev = "188f542"; # "v${version}";
# owner = "imgurbot12";
# repo = pname;
# hash = "sha256-IRwYxjyHdP6794pQjyyUmofO8uakMY22pqdFkJZ5Mdo=";
# };
strictDeps = true;
cargoLock = {
lockFile = ../Cargo.lock;
outputHashes = {
"gio-0.19.0" = "sha256-+PAQNJ9sTk8aKAhA/PLQWDCKDT/cQ+ukdbem7g1J+pU=";
"nm-0.4.0" = "sha256-53ipJU10ZhIKIF7PCw5Eo/e/reUK0qpyTyE7uIrCD88=";
};
};
nativeBuildInputs = [
pkg-config
wrapGAppsHook
];
buildInputs = [
glib
gtk3
libsoup_3
networkmanager
webkitgtk_4_1
gnused
];
postInstall = ''
# copy themes and plugins
mkdir $out/themes
mkdir $out/plugins
cp -vfr $src/themes/* $out/themes/.
cp -vfr $src/other-plugins/* $out/plugins/.
mv $out/bin/* $out/plugins # everything is a plugin by default
# rmenu and rmenu-build are actual binaries
mv $out/plugins/rmenu $out/bin/rmenu
mv $out/plugins/rmenu-build $out/bin/rmenu-build
# fix plugin names
# desktop network pactl-audio.sh powermenu.sh run window
mv $out/plugins/run $out/plugins/rmenu-run
mv $out/plugins/desktop $out/plugins/rmenu-desktop
mv $out/plugins/network $out/plugins/rmenu-network
mv $out/plugins/window $out/plugins/rmenu-window
# fix config and theme
mkdir -p $out/etc/xdg/rmenu
cp -vf $src/rmenu/public/config.yaml $out/etc/xdg/rmenu/config.yaml
sed -i "s@~\/\.config\/rmenu\/themes@$out\/themes@g" $out/etc/xdg/rmenu/config.yaml
sed -i "s@~\/\.config\/rmenu@$out\/plugins@g" $out/etc/xdg/rmenu/config.yaml
ln -sf $out/themes/dark.css $out/etc/xdg/rmenu/style.css
'';
doCheck = true;
meta = with lib; {
changelog = "https://github.com/imgurbot12/rmenu/commits/master/";
description = "Another customizable Application-Launcher written in Rust ";
homepage = "https://github.com/imgurbot12/rmenu";
mainProgram = "rmenu";
maintainers = [ maintainers.grimmauld ];
platforms = platforms.linux;
};
}

View File

@ -1,8 +0,0 @@
{ lib, pkgs, ... }:
let
rmenu-pkg = pkgs.callPackage ./package.nix {};
in {
config.environment.systemPackages = [ rmenu-pkg ];
meta.maintainers = with lib.maintainers; [ grimmauld ];
}

View File

@ -1,6 +1,3 @@
body {
padding: 0;
}
.navbar {
width: 0;
@ -12,10 +9,6 @@ body {
display: flex;
justify-content: center;
align-items: center;
height: 100vh;
min-height: 100vh;
overflow-y: hidden;
}
.result {

View File

@ -4,6 +4,7 @@ get_sinks() {
sinks=`pactl list sinks | grep -e 'Sink #' -e 'Name: ' -e 'Description: ' | nl -s '>'`
default=`pactl get-default-sink`
for i in `seq 1 3 $(echo "$sinks" | wc -l)`; do
echo "$sinks" | grep "$i>"
sink=`echo "$sinks" | grep "$i>" | cut -d '#' -f2`
name=`echo "$sinks" | grep "$(expr $i + 1)>" | cut -d ':' -f2 | xargs echo -n`
desc=`echo "$sinks" | grep "$(expr $i + 2)>" | cut -d ':' -f2 | xargs echo -n`

View File

@ -1,13 +1,13 @@
[package]
name = "rmenu"
version = "1.1.1"
version = "0.0.1"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
cached = "0.44.0"
clap = { version = "4.3.15", features = ["derive", "env"] }
clap = { version = "4.3.15", features = ["derive"] }
dioxus = "0.4.3"
dioxus-desktop = "0.4.3"
dioxus-html = "0.4.3"
@ -30,4 +30,3 @@ shellexpand = "3.1.0"
strfmt = "0.2.4"
thiserror = "1.0.43"
which = "4.4.0"
xdg = "2.5.2"

View File

@ -1,19 +1,19 @@
body {
overflow: hidden;
}
body > div {
height: -webkit-fill-available;
overflow: hidden;
}
html,
body,
.content {
margin: 0;
}
body {
overflow: hidden;
padding-top: 60px;
}
body>div {
height: -webkit-fill-available;
overflow: hidden;
}
.navbar {
top: 0;
left: 0;
@ -23,10 +23,9 @@ body>div {
}
.results {
height: 100vh;
margin-top: 50px;
overflow-y: auto;
height: calc(100vh - 60px);
min-height: calc(100vh - 60px);
scroll-margin-top: 60px;
}
.selected {
@ -44,21 +43,19 @@ input {
height: 5vw;
border: none;
outline: none;
padding: 5px;
font-size: large;
padding: 5px;
font-size: large;
}
/* Result CSS */
.result,
.action {
.result, .action {
display: flex;
align-items: center;
justify-content: left;
}
.result>div,
.action>div {
.result > div, .action > div {
margin: 2px 5px;
}

View File

@ -3,11 +3,15 @@ use std::fs;
use std::path::PathBuf;
use std::time::{Duration, SystemTime};
use once_cell::sync::Lazy;
use rmenu_plugin::Entry;
use thiserror::Error;
use crate::config::{CacheSetting, PluginConfig};
use crate::XDG_PREFIX;
use crate::CONFIG_DIR;
static CONFIG_PATH: Lazy<PathBuf> =
Lazy::new(|| PathBuf::from(shellexpand::tilde(CONFIG_DIR).to_string()));
#[derive(Debug, Error)]
pub enum CacheError {
@ -25,10 +29,7 @@ pub enum CacheError {
#[inline]
fn cache_file(name: &str) -> PathBuf {
xdg::BaseDirectories::with_prefix(XDG_PREFIX)
.expect("Failed to read xdg base dirs")
.place_cache_file(format!("{name}.cache"))
.expect("Failed to write xdg cache dirs")
CONFIG_PATH.join(format!("{name}.cache"))
}
/// Read Entries from Cache (if Valid and Available)

View File

@ -1,6 +1,5 @@
use std::fs::File;
use std::io::{BufRead, BufReader, Read};
use std::path::PathBuf;
use std::process::{Command, ExitStatus, Stdio};
use std::str::FromStr;
use std::{fmt::Display, fs::read_to_string};
@ -10,7 +9,7 @@ use rmenu_plugin::{Entry, Message};
use thiserror::Error;
use crate::config::{cfg_replace, Config, Keybind};
use crate::{DEFAULT_CONFIG, DEFAULT_THEME, XDG_PREFIX};
use crate::{DEFAULT_CONFIG, DEFAULT_CSS};
/// Allowed Formats for Entry Ingestion
#[derive(Debug, Clone)]
@ -53,18 +52,18 @@ pub struct Args {
#[arg(short, long)]
run: Vec<String>,
/// Override default configuration path
#[arg(short, long, env = "RMENU_CONFIG")]
config: Option<PathBuf>,
#[arg(short, long)]
config: Option<String>,
/// Override base css theme styling
#[arg(long, env = "RMENU_THEME")]
theme: Option<PathBuf>,
#[arg(long, default_value_t=String::from(DEFAULT_CSS))]
theme: String,
/// Include additional css settings
#[arg(long, env = "RMENU_CSS")]
css: Option<PathBuf>,
#[arg(long)]
css: Option<String>,
// root config settings
/// Override terminal command
#[arg(long, env = "RMENU_TERMINAL")]
#[arg(long)]
terminal: Option<String>,
/// Number of results to include for each page
#[arg(long)]
@ -179,37 +178,23 @@ pub enum RMenuError {
pub type Result<T> = std::result::Result<T, RMenuError>;
impl Args {
/// Find a specifically named file across xdg config paths
fn find_xdg_file(&self, name: &str, base: &Option<PathBuf>) -> Option<String> {
return base
.clone()
.or_else(|| {
xdg::BaseDirectories::with_prefix(XDG_PREFIX)
.expect("Failed to read xdg base dirs")
.find_config_file(name)
})
.map(|f| {
let f = f.to_string_lossy().to_string();
shellexpand::tilde(&f).to_string()
});
}
/// Load Configuration File
pub fn get_config(&self) -> Result<Config> {
let config = self.find_xdg_file(DEFAULT_CONFIG, &self.config);
if let Some(path) = config {
let config: Config = match read_to_string(path) {
Ok(content) => serde_yaml::from_str(&content),
Err(err) => {
log::error!("Failed to Load Config: {err:?}");
Ok(Config::default())
}
}?;
return Ok(config);
}
log::error!("Failed to Load Config: no file found in xdg config paths");
Ok(Config::default())
// read configuration
let path = self
.config
.as_ref()
.map(|v| v.as_str())
.unwrap_or(DEFAULT_CONFIG);
let path = shellexpand::tilde(path).to_string();
let config: Config = match read_to_string(path) {
Ok(content) => serde_yaml::from_str(&content),
Err(err) => {
log::error!("Failed to Load Config: {err:?}");
Ok(Config::default())
}
}?;
Ok(config)
}
/// Update Configuration w/ CLI Specified Settings
@ -252,28 +237,22 @@ impl Args {
/// Load CSS Theme or Default
pub fn get_theme(&self) -> String {
self.find_xdg_file(DEFAULT_THEME, &self.theme)
.map(read_to_string)
.map(|f| {
f.unwrap_or_else(|err| {
log::error!("Failed to load CSS: {err:?}");
String::new()
})
})
.unwrap_or_else(String::new)
let path = shellexpand::tilde(&self.theme).to_string();
match read_to_string(&path) {
Ok(css) => css,
Err(err) => {
log::error!("Failed to load CSS: {err:?}");
String::new()
}
}
}
/// Load Additional CSS or Default
pub fn get_css(&self, c: &Config) -> String {
let css = self
.css
.clone()
.map(|s| s.to_string_lossy().to_string())
.or(c.css.clone());
if let Some(path) = css {
let path = shellexpand::tilde(&path).to_string();
if let Some(css) = self.css.as_ref().or(c.css.as_ref()) {
let path = shellexpand::tilde(&css).to_string();
match read_to_string(&path) {
Ok(css) => return css,
Ok(theme) => return theme,
Err(err) => log::error!("Failed to load Theme: {err:?}"),
}
}

View File

@ -1,4 +1,7 @@
//! RMENU Configuration Implementations
use heck::AsPascalCase;
use rmenu_plugin::Options;
use serde::{de::Error, Deserialize};
use std::collections::BTreeMap;
use std::str::FromStr;
@ -7,9 +10,6 @@ use dioxus_desktop::tao::{
window::Fullscreen,
};
use dioxus_html::input_data::keyboard_types::{Code, Modifiers};
use heck::AsPascalCase;
use rmenu_plugin::Options;
use serde::{de::Error, Deserialize};
// parse supported modifiers from string
fn mod_from_str(s: &str) -> Option<Modifiers> {

View File

@ -10,9 +10,9 @@ mod state;
use clap::Parser;
use rmenu_plugin::{self_exe, Entry};
static DEFAULT_THEME: &'static str = "style.css";
static DEFAULT_CONFIG: &'static str = "config.yaml";
static XDG_PREFIX: &'static str = "rmenu";
static CONFIG_DIR: &'static str = "~/.config/rmenu/";
static DEFAULT_CSS: &'static str = "~/.config/rmenu/style.css";
static DEFAULT_CONFIG: &'static str = "~/.config/rmenu/config.yaml";
static DEFAULT_CSS_CONTENT: &'static str = include_str!("../public/default.css");
/// Application State for GUI
@ -45,6 +45,8 @@ fn main() -> cli::Result<()> {
let mut cli = cli::Args::parse();
let mut config = cli.get_config()?;
let entries = cli.get_entries(&mut config)?;
let css = cli.get_css(&config);
let theme = cli.get_theme();
// update config based on cli-settings and entries
config = cli.update_config(config);
@ -54,8 +56,11 @@ fn main() -> cli::Result<()> {
.any(|e| e.icon.is_some() || e.icon_alt.is_some());
config.use_comments = config.use_comments && entries.iter().any(|e| e.comment.is_some());
let theme = cli.get_theme();
let css = cli.get_css(&config);
// change directory to config folder
let cfgdir = shellexpand::tilde(CONFIG_DIR).to_string();
if let Err(err) = std::env::set_current_dir(&cfgdir) {
log::error!("failed to change directory: {err:?}");
}
// genrate app context and run gui
gui::run(App {

View File

@ -1,2 +0,0 @@
[toolchain]
channel = "stable"