+
Skip to content

Config and emoji #49

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 5 commits into from
May 3, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
439 changes: 427 additions & 12 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -47,3 +47,5 @@ meval = "0.2.0"
tree_magic_mini = "3.1.6"
rayon = "1.10.0"
nix = { version = "0.30.0", features = ["process"] }
emoji = "0.2.1"
wl-clipboard-rs = "0.9.2"
13 changes: 9 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,19 +13,24 @@ It supports various modes:
* File
* Ssh
* Run
* Emoji
* // WebSearch
* // Emoji

* Auto

Auto mode tries to detect the desired mode automatically, i.e. `ssh`, `?` (for web search), `emoji`, `/` or `~` (for file).
Auto mode tries to detect the desired mode automatically, to achieve this some modes require a prefix in the search.
The standard view will show `ssh` and `drun`, for other modes the following prefixes are available:
* `ssh` (optional)
* `?` web search
* `/`, `$` or `~` for files
* `emoji` for emojis

<img src="images/demo.gif" style="width:600px;">
<img src="images/demo.gif">

## Not finished
* [ ] key support
* [ ] full config support
* [ ] web search mode
* [ ] emoji finder
* [ ] publish library


Expand Down
68 changes: 37 additions & 31 deletions src/lib/config.rs
Original file line number Diff line number Diff line change
@@ -1,27 +1,13 @@
use std::path::PathBuf;
use std::str::FromStr;
use std::{env, fmt, fs};
use std::{env, fs};

use anyhow::anyhow;
use crate::Error;
use clap::{Parser, ValueEnum};
use serde::{Deserialize, Serialize};
use serde_json::Value;
use thiserror::Error;

#[derive(Debug)]
pub enum ConfigurationError {
Open(String),
Parse(String),
}

impl fmt::Display for ConfigurationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
ConfigurationError::Open(e) | ConfigurationError::Parse(e) => write!(f, "{e}"),
}
}
}

#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug, Serialize, Deserialize)]
pub enum Anchor {
Top,
Expand Down Expand Up @@ -79,6 +65,9 @@ pub enum Mode {

/// Connect via ssh to a given host
Ssh,

/// Emoji browser
Emoji,
}

#[derive(Debug, Error)]
Expand Down Expand Up @@ -112,6 +101,7 @@ impl FromStr for Mode {
"file" => Ok(Mode::File),
"math" => Ok(Mode::Math),
"ssh" => Ok(Mode::Ssh),
"emoji" => Ok(Mode::Emoji),
"auto" => Ok(Mode::Auto),
_ => Err(ArgsError::InvalidParameter(
format!("{s} is not a valid argument, see help for details").to_owned(),
Expand Down Expand Up @@ -188,8 +178,9 @@ pub struct Config {
#[clap(short = 'I', long = "allow-images")]
allow_images: Option<bool>,

/// If `true` pango markup is parsed
#[clap(short = 'm', long = "allow-markup")]
allow_markup: Option<bool>, // todo support this
allow_markup: Option<bool>,

#[clap(short = 'k', long = "cache-file")]
cache_file: Option<String>, // todo support this
Expand Down Expand Up @@ -223,6 +214,8 @@ pub struct Config {
#[clap(short = 'M', long = "matching")]
matching: Option<MatchMethod>,

/// Control if search is case-insensitive or not.
/// Defaults to true
#[clap(short = 'i', long = "insensitive")]
insensitive: Option<bool>,

Expand All @@ -249,7 +242,7 @@ pub struct Config {
sort_order: Option<String>,

#[clap(short = 'Q', long = "search")]
search: Option<String>, // todo support this
search: Option<String>,

#[clap(short = 'o', long = "monitor")]
monitor: Option<String>, // todo support this
Expand Down Expand Up @@ -405,6 +398,7 @@ impl Config {
Mode::File => "file".to_owned(),
Mode::Auto => "auto".to_owned(),
Mode::Ssh => "ssh".to_owned(),
Mode::Emoji => "emoji".to_owned(),
},
},

Expand Down Expand Up @@ -484,12 +478,26 @@ impl Config {
pub fn hide_search(&self) -> bool {
self.hide_search.unwrap_or(false)
}

#[must_use]
pub fn search(&self) -> Option<String> {
self.search.clone()
}

#[must_use]
pub fn allow_markup(&self) -> bool {
self.allow_markup.unwrap_or(false)
}
}

fn default_false() -> bool {
false
}

// fn default_true() -> bool {
// true
// }

//
// // TODO
// // GtkOrientation orientation = config_get_mnemonic(config, "orientation", "vertical", 2, "vertical", "horizontal");
Expand All @@ -503,7 +511,6 @@ fn default_false() -> bool {
// // GtkAlign valign = config_get_mnemonic(config, "valign", default_valign, 4, "fill", "start", "end", "center");
// // char* prompt = config_get(config, "prompt", mode);
// // uint64_t filter_rate = strtol(config_get(config, "filter_rate", "100"), NULL, 10);
// // allow_images = strcmp(config_get(config, "allow_images", "false"), "true") == 0;
// // allow_markup = strcmp(config_get(config, "allow_markup", "false"), "true") == 0;
// // image_size = strtol(config_get(config, "image_size", "32"), NULL, 10);
// // cache_file = map_get(config, "cache_file");
Expand Down Expand Up @@ -576,7 +583,7 @@ pub fn parse_args() -> Config {
/// # Errors
///
/// Will return Err when it cannot resolve any path or no style is found
fn style_path(full_path: Option<String>) -> Result<PathBuf, anyhow::Error> {
fn style_path(full_path: Option<String>) -> Result<PathBuf, Error> {
let alternative_paths = path_alternatives(
vec![dirs::config_dir()],
&PathBuf::from("worf").join("style.css"),
Expand All @@ -587,7 +594,7 @@ fn style_path(full_path: Option<String>) -> Result<PathBuf, anyhow::Error> {
/// # Errors
///
/// Will return Err when it cannot resolve any path or no style is found
pub fn conf_path(full_path: Option<String>) -> Result<PathBuf, anyhow::Error> {
pub fn conf_path(full_path: Option<String>) -> Result<PathBuf, Error> {
let alternative_paths = path_alternatives(
vec![dirs::config_dir()],
&PathBuf::from("worf").join("config"),
Expand All @@ -612,7 +619,7 @@ pub fn path_alternatives(base_paths: Vec<Option<PathBuf>>, sub_path: &PathBuf) -
pub fn resolve_path(
full_path: Option<String>,
alternatives: Vec<PathBuf>,
) -> Result<PathBuf, anyhow::Error> {
) -> Result<PathBuf, Error> {
full_path
.map(PathBuf::from)
.and_then(|p| p.canonicalize().ok().filter(|c| c.exists()))
Expand All @@ -622,7 +629,7 @@ pub fn resolve_path(
.filter(|p| p.exists())
.find_map(|pb| pb.canonicalize().ok().filter(|c| c.exists()))
})
.ok_or_else(|| anyhow!("Could not find a valid file."))
.ok_or(Error::MissingFile)
}

/// # Errors
Expand All @@ -632,25 +639,24 @@ pub fn resolve_path(
/// * cannot parse the config file
/// * no config file exists
/// * config file and args cannot be merged
pub fn load_config(args_opt: Option<Config>) -> Result<Config, ConfigurationError> {
pub fn load_config(args_opt: Option<&Config>) -> Result<Config, Error> {
let config_path = conf_path(args_opt.as_ref().and_then(|c| c.config.clone()));
match config_path {
Ok(path) => {
let toml_content =
fs::read_to_string(path).map_err(|e| ConfigurationError::Open(format!("{e}")))?;
let mut config: Config = toml::from_str(&toml_content)
.map_err(|e| ConfigurationError::Parse(format!("{e}")))?;
let toml_content = fs::read_to_string(path).map_err(|e| Error::Io(format!("{e}")))?;
let mut config: Config =
toml::from_str(&toml_content).map_err(|e| Error::ParsingError(format!("{e}")))?;

if let Some(args) = args_opt {
let merge_result = merge_config_with_args(&mut config, &args)
.map_err(|e| ConfigurationError::Parse(format!("{e}")))?;
let merge_result = merge_config_with_args(&mut config, args)
.map_err(|e| Error::ParsingError(format!("{e}")))?;
Ok(merge_result)
} else {
Ok(config)
}
}

Err(e) => Err(ConfigurationError::Open(format!("{e}"))),
Err(e) => Err(Error::Io(format!("{e}"))),
}
}

Expand Down
28 changes: 23 additions & 5 deletions src/lib/desktop.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,3 @@
use crate::Error;
use crate::config::expand_path;
use freedesktop_file_parser::DesktopFile;
use rayon::prelude::*;
use regex::Regex;
use std::collections::HashMap;
use std::os::unix::fs::PermissionsExt;
use std::os::unix::prelude::CommandExt;
Expand All @@ -12,6 +7,14 @@ use std::process::{Command, Stdio};
use std::time::Instant;
use std::{env, fs, io};

use freedesktop_file_parser::DesktopFile;
use rayon::prelude::*;
use regex::Regex;
use wl_clipboard_rs::copy::{ClipboardType, MimeType, ServeRequests, Source};

use crate::Error;
use crate::config::expand_path;

/// Returns a regex with supported image extensions
/// # Panics
///
Expand Down Expand Up @@ -291,3 +294,18 @@ pub fn is_executable(entry: &Path) -> bool {
false
}
}

/// Copy the given text into the clipboard.
/// # Errors
/// Will return an error if copying to the clipboard failed.
pub fn copy_to_clipboard(text: String) -> Result<(), Error> {
let mut opts = wl_clipboard_rs::copy::Options::new();
opts.clipboard(ClipboardType::Regular);
opts.serve_requests(ServeRequests::Only(1));
let result = opts.copy(Source::Bytes(text.into_bytes().into()), MimeType::Text);

match result {
Ok(()) => Ok(()),
Err(e) => Err(Error::Clipboard(e.to_string())),
}
}
Loading
点击 这是indexloc提供的php浏览器服务,不要输入任何密码和下载