Initial commit

This commit is contained in:
lelgenio 2023-01-21 01:47:15 -03:00
parent 87f139acd4
commit afe472b3e3
6 changed files with 1517 additions and 0 deletions

1
.gitignore vendored Normal file
View file

@ -0,0 +1 @@
target

1190
Cargo.lock generated Normal file

File diff suppressed because it is too large Load diff

158
Cargo.toml Normal file
View file

@ -0,0 +1,158 @@
[package]
name = "demoji"
version = "0.1.0"
edition = "2021"
[dependencies]
clap = { version = "4.1.1", features = ["derive"] }
fork = "0.1.20"
arboard = { version = "3.2.0", features = ["wayland-data-control"] }
[dependencies.emoji]
version = "0.2.1"
[features]
default = [ "en" ]
af = [ "emoji/af" ]
am = [ "emoji/am" ]
ar = [ "emoji/ar" ]
ar_SA = [ "emoji/ar_SA" ]
as = [ "emoji/as" ]
ast = [ "emoji/ast" ]
az = [ "emoji/az" ]
be = [ "emoji/be" ]
bg = [ "emoji/bg" ]
bn = [ "emoji/bn" ]
br = [ "emoji/br" ]
bs = [ "emoji/bs" ]
ca = [ "emoji/ca" ]
ccp = [ "emoji/ccp" ]
ceb = [ "emoji/ceb" ]
chr = [ "emoji/chr" ]
ckb = [ "emoji/ckb" ]
cs = [ "emoji/cs" ]
cy = [ "emoji/cy" ]
da = [ "emoji/da" ]
de = [ "emoji/de" ]
de_CH = [ "emoji/de_CH" ]
doi = [ "emoji/doi" ]
el = [ "emoji/el" ]
en = [ "emoji/en" ]
en_001 = [ "emoji/en_001" ]
en_AU = [ "emoji/en_AU" ]
en_CA = [ "emoji/en_CA" ]
en_GB = [ "emoji/en_GB" ]
en_IN = [ "emoji/en_IN" ]
es = [ "emoji/es" ]
es_419 = [ "emoji/es_419" ]
es_MX = [ "emoji/es_MX" ]
es_US = [ "emoji/es_US" ]
et = [ "emoji/et" ]
eu = [ "emoji/eu" ]
fa = [ "emoji/fa" ]
fi = [ "emoji/fi" ]
fil = [ "emoji/fil" ]
fo = [ "emoji/fo" ]
fr = [ "emoji/fr" ]
fr_CA = [ "emoji/fr_CA" ]
ga = [ "emoji/ga" ]
gd = [ "emoji/gd" ]
gl = [ "emoji/gl" ]
gu = [ "emoji/gu" ]
ha = [ "emoji/ha" ]
ha_NE = [ "emoji/ha_NE" ]
he = [ "emoji/he" ]
hi = [ "emoji/hi" ]
hr = [ "emoji/hr" ]
hu = [ "emoji/hu" ]
hy = [ "emoji/hy" ]
ia = [ "emoji/ia" ]
id = [ "emoji/id" ]
ig = [ "emoji/ig" ]
is = [ "emoji/is" ]
it = [ "emoji/it" ]
ja = [ "emoji/ja" ]
jv = [ "emoji/jv" ]
ka = [ "emoji/ka" ]
kab = [ "emoji/kab" ]
kk = [ "emoji/kk" ]
kl = [ "emoji/kl" ]
km = [ "emoji/km" ]
kn = [ "emoji/kn" ]
ko = [ "emoji/ko" ]
kok = [ "emoji/kok" ]
ku = [ "emoji/ku" ]
ky = [ "emoji/ky" ]
lb = [ "emoji/lb" ]
lo = [ "emoji/lo" ]
lt = [ "emoji/lt" ]
lv = [ "emoji/lv" ]
mai = [ "emoji/mai" ]
mi = [ "emoji/mi" ]
mk = [ "emoji/mk" ]
ml = [ "emoji/ml" ]
mn = [ "emoji/mn" ]
mni = [ "emoji/mni" ]
mr = [ "emoji/mr" ]
ms = [ "emoji/ms" ]
mt = [ "emoji/mt" ]
my = [ "emoji/my" ]
nb = [ "emoji/nb" ]
ne = [ "emoji/ne" ]
nl = [ "emoji/nl" ]
nn = [ "emoji/nn" ]
or = [ "emoji/or" ]
pa = [ "emoji/pa" ]
pa_Arab = [ "emoji/pa_Arab" ]
pcm = [ "emoji/pcm" ]
pl = [ "emoji/pl" ]
ps = [ "emoji/ps" ]
pt = [ "emoji/pt" ]
pt_PT = [ "emoji/pt_PT" ]
qu = [ "emoji/qu" ]
rm = [ "emoji/rm" ]
ro = [ "emoji/ro" ]
root = [ "emoji/root" ]
ru = [ "emoji/ru" ]
rw = [ "emoji/rw" ]
sa = [ "emoji/sa" ]
sat = [ "emoji/sat" ]
sd = [ "emoji/sd" ]
si = [ "emoji/si" ]
sk = [ "emoji/sk" ]
sl = [ "emoji/sl" ]
so = [ "emoji/so" ]
sq = [ "emoji/sq" ]
sr = [ "emoji/sr" ]
sr_Cyrl = [ "emoji/sr_Cyrl" ]
sr_Cyrl_BA = [ "emoji/sr_Cyrl_BA" ]
sr_Latn = [ "emoji/sr_Latn" ]
sr_Latn_BA = [ "emoji/sr_Latn_BA" ]
su = [ "emoji/su" ]
sv = [ "emoji/sv" ]
sw = [ "emoji/sw" ]
sw_KE = [ "emoji/sw_KE" ]
ta = [ "emoji/ta" ]
te = [ "emoji/te" ]
tg = [ "emoji/tg" ]
th = [ "emoji/th" ]
ti = [ "emoji/ti" ]
tk = [ "emoji/tk" ]
to = [ "emoji/to" ]
tr = [ "emoji/tr" ]
tt = [ "emoji/tt" ]
ug = [ "emoji/ug" ]
uk = [ "emoji/uk" ]
ur = [ "emoji/ur" ]
uz = [ "emoji/uz" ]
vi = [ "emoji/vi" ]
wo = [ "emoji/wo" ]
xh = [ "emoji/xh" ]
yo = [ "emoji/yo" ]
yo_BJ = [ "emoji/yo_BJ" ]
yue = [ "emoji/yue" ]
yue_Hans = [ "emoji/yue_Hans" ]
zh = [ "emoji/zh" ]
zh_Hant = [ "emoji/zh_Hant" ]
zh_Hant_HK = [ "emoji/zh_Hant_HK" ]
zu = [ "emoji/zu" ]

24
flake.lock Normal file
View file

@ -0,0 +1,24 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1673800717,
"narHash": "sha256-SFHraUqLSu5cC6IxTprex/nTsI81ZQAtDvlBvGDWfnA=",
"path": "/nix/store/d6vlzbp9x6ixk1d1gr7if0f2ji6s8q4v-source",
"rev": "2f9fd351ec37f5d479556cd48be4ca340da59b8f",
"type": "path"
},
"original": {
"id": "nixpkgs",
"type": "indirect"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

29
flake.nix Normal file
View file

@ -0,0 +1,29 @@
{
description = "Pick emojis using dmenu";
inputs = { };
outputs = { self, nixpkgs, ... }:
let
system = "x86_64-linux";
pkgs = nixpkgs.legacyPackages.${system};
definition = { pkgs, languages ? [ ] }:
pkgs.rustPlatform.buildRustPackage {
pname = "demoji";
version = "0.1";
src = pkgs.lib.cleanSource ./.;
cargoLock.lockFile = ./Cargo.lock;
cargoBuildFlags = if languages == [ ] then "--all-features" else "--features ${pkgs.lib.concatStringSep "," languages}";
};
outputs = with pkgs; {
packages.${system} = {
default = self.packages.${system}.demoji;
demoji = pkgs.callPackage definition { };
};
devShells.${system}.default =
mkShell { nativeBuildInputs = [ xorg.libxcb ]; };
};
in outputs;
}

115
src/main.rs Normal file
View file

@ -0,0 +1,115 @@
use std::{io::Write, time::Duration};
use arboard::SetExtLinux;
use clap::Parser;
use emoji;
/// Simple program to list all emojis
#[derive(Parser, Debug)]
// #[command(author, version, about, long_about = None)]
struct Args {
/// What language to use for the descriptions
#[arg(short, long, default_value_t = {"en".to_string()})]
lang: String,
/// Fallback to english descriptions when not found
#[arg(short, long, default_value_t = false)]
fallback: bool,
/// Send dmenu command output to clipoard
#[arg(short, long, default_value_t = false)]
copy: bool,
/// dmenu-like command to wrap for querying
#[arg(last = true, allow_hyphen_values = true)]
dmenu_command: Option<Vec<String>>,
}
fn main() {
let args = Args::parse();
let out = std::io::stdout().lock();
match args.dmenu_command {
Some(ref c) => {
let out = pick_emoji_dmenu(c, &args);
if args.copy {
send_to_clipboard(out.to_string());
}
}
None => {
write_emojis_to_stdout(&args, out);
}
}
}
fn pick_emoji_dmenu(c: &Vec<String>, args: &Args) -> char {
let child_stdout = if args.copy {
std::process::Stdio::piped()
} else {
std::process::Stdio::inherit()
};
let mut child = std::process::Command::new(&c[0])
.args(&c[1..])
.stdin(std::process::Stdio::piped())
.stdout(child_stdout)
.spawn()
.unwrap();
let stdin = child.stdin.take().unwrap();
write_emojis_to_stdout(args, stdin);
if !args.copy {
return ' ';
}
let output = child.wait_with_output().unwrap();
let out = String::from_utf8_lossy(&output.stdout)
.chars()
.take(1)
.next()
.unwrap_or_else(|| std::process::exit(1));
out
}
fn send_to_clipboard(out: String) {
if let Ok(fork::Fork::Parent(_)) = fork::fork() {
std::thread::sleep(Duration::from_millis(100));
} else {
eprintln!("Setting clipboard to emoji '{out}'");
let mut clip = arboard::Clipboard::new().unwrap();
clip.set().wait().text(out.clone()).unwrap();
}
}
fn write_emojis_to_stdout(args: &Args, mut out: impl Write) {
for emoji in emoji::lookup_by_glyph::iter_emoji() {
let native_description = emoji_description(emoji, &args.lang);
let fallback_description = emoji_description(emoji, "en");
let basic_description = emoji.name.to_string();
let text = match (native_description, fallback_description) {
(Some(native), Some(fallback)) if args.fallback => {
format!("{} {}", native, fallback)
}
(Some(native), _) => native,
(_, Some(fallback)) if args.fallback => fallback,
_ if args.fallback => basic_description,
_ => continue,
};
writeln!(&mut out, "{}: {}", emoji.glyph, text).ok();
}
}
fn emoji_description(emoji: &emoji::Emoji, lang: &str) -> Option<String> {
let annotations = emoji.annotations.iter().find(|a| a.lang == lang)?;
let keywords = annotations.keywords.join(" ");
if let Some(annotations) = annotations.tts {
Some(format!("{} {}", annotations, keywords))
} else if !keywords.is_empty() {
Some(keywords)
} else {
None
}
}