Skip to content

Commit

Permalink
Merge pull request #381 from xrelkd/feat/macos
Browse files Browse the repository at this point in the history
Add support for `macOS`
  • Loading branch information
xrelkd committed Apr 21, 2024
2 parents c3bbee7 + f2a4422 commit f19760c
Show file tree
Hide file tree
Showing 20 changed files with 746 additions and 66 deletions.
3 changes: 3 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

84 changes: 82 additions & 2 deletions clipcat-menu/src/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,9 @@ pub struct Config {
#[serde(default)]
pub dmenu: Option<Dmenu>,

#[serde(default)]
pub choose: Option<Choose>,

#[serde(default)]
pub custom_finder: Option<CustomFinder>,

Expand Down Expand Up @@ -104,10 +107,25 @@ impl Default for Config {
server_endpoint: clipcat_base::config::default_server_endpoint(),
access_token: None,
access_token_file_path: None,

#[cfg(all(
unix,
not(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "emscripten"
))
))]
finder: FinderType::Rofi,

#[cfg(target_os = "macos")]
finder: FinderType::Choose,

preview_length: 80,
rofi: Some(Rofi::default()),
dmenu: Some(Dmenu::default()),
choose: Some(Choose::default()),
custom_finder: Some(CustomFinder::default()),
log: clipcat_cli::config::LogConfig::default(),
}
Expand Down Expand Up @@ -144,6 +162,21 @@ pub struct Dmenu {
pub extra_arguments: Vec<String>,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct Choose {
#[serde(default = "default_line_length")]
pub line_length: usize,

#[serde(default = "default_menu_length")]
pub menu_length: usize,

#[serde(default = "default_menu_prompt")]
pub menu_prompt: String,

#[serde(default)]
pub extra_arguments: Vec<String>,
}

#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
pub struct CustomFinder {
pub program: String,
Expand Down Expand Up @@ -173,15 +206,62 @@ impl Default for Dmenu {
}
}

impl Default for Choose {
fn default() -> Self {
Self {
menu_prompt: default_menu_prompt(),
menu_length: default_menu_length(),
line_length: default_line_length(),
extra_arguments: Vec::new(),
}
}
}

impl Default for CustomFinder {
fn default() -> Self { Self { program: "fzf".to_string(), args: Vec::new() } }
}

fn default_menu_prompt() -> String { clipcat_base::DEFAULT_MENU_PROMPT.to_string() }

const fn default_menu_length() -> usize { 30 }
const fn default_menu_length() -> usize {
#[cfg(all(
unix,
not(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "emscripten"
))
))]
{
30
}

#[cfg(target_os = "macos")]
{
15
}
}

const fn default_line_length() -> usize { 100 }
const fn default_line_length() -> usize {
#[cfg(all(
unix,
not(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "emscripten"
))
))]
{
100
}

#[cfg(target_os = "macos")]
{
70
}
}

#[derive(Debug, Snafu)]
pub enum Error {
Expand Down
103 changes: 103 additions & 0 deletions clipcat-menu/src/finder/external/choose.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
use clipcat_base::ClipEntryMetadata;

use crate::{
config,
finder::{
external::ExternalProgram, finder_stream::ENTRY_SEPARATOR, FinderStream, SelectionMode,
},
};

#[derive(Clone, Debug, Eq, PartialEq)]
pub struct Choose {
line_length: usize,
menu_length: usize,
menu_prompt: String,
extra_arguments: Vec<String>,
}

impl From<config::Choose> for Choose {
fn from(
config::Choose { menu_length, line_length, menu_prompt, extra_arguments }: config::Choose,
) -> Self {
Self { line_length, menu_length, menu_prompt, extra_arguments }
}
}

impl ExternalProgram for Choose {
fn program(&self) -> String { "choose".to_string() }

fn args(&self, _selection_mode: SelectionMode) -> Vec<String> {
Vec::new()
.into_iter()
.chain([
"-i".to_string(),
"-n".to_string(),
self.menu_length.to_string(),
"-w".to_string(),
self.line_length.to_string(),
"-p".to_string(),
self.menu_prompt.clone(),
])
.chain(self.extra_arguments.clone())
.collect()
}
}

impl FinderStream for Choose {
fn generate_input(&self, clips: &[ClipEntryMetadata]) -> String {
clips.iter().map(|clip| clip.preview.clone()).collect::<Vec<_>>().join(ENTRY_SEPARATOR)
}

fn parse_output(&self, data: &[u8]) -> Vec<usize> {
String::from_utf8_lossy(data)
.trim()
.split(ENTRY_SEPARATOR)
.filter_map(|index| index.parse().ok())
.collect()
}

fn line_length(&self) -> Option<usize> { Some(self.line_length) }

fn menu_length(&self) -> Option<usize> { Some(self.menu_length) }

fn set_line_length(&mut self, line_length: usize) { self.line_length = line_length }

fn set_menu_length(&mut self, menu_length: usize) { self.menu_length = menu_length; }

fn set_extra_arguments(&mut self, arguments: &[String]) {
self.extra_arguments = arguments.to_vec();
}
}

#[cfg(test)]
mod tests {
use crate::{
config,
finder::{external::ExternalProgram, Choose, SelectionMode},
};

#[test]
fn test_args() {
let menu_length = 30;
let menu_prompt = clipcat_base::DEFAULT_MENU_PROMPT.to_owned();
let config = config::Choose {
line_length: 40,
menu_length,
menu_prompt,
extra_arguments: Vec::new(),
};
let choose = Choose::from(config.clone());
assert_eq!(
choose.args(SelectionMode::Single),
vec![
"-i".to_string(),
"-n".to_string(),
config.menu_length.to_string(),
"-w".to_string(),
config.line_length.to_string(),
"-p".to_string(),
config.menu_prompt,
]
);
}
}
3 changes: 2 additions & 1 deletion clipcat-menu/src/finder/external/mod.rs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
mod choose;
mod custom;
mod dmenu;
mod fzf;
Expand All @@ -8,7 +9,7 @@ use std::{path::PathBuf, process::Stdio};

use tokio::process::Command;

pub use self::{custom::Custom, dmenu::Dmenu, fzf::Fzf, rofi::Rofi, skim::Skim};
pub use self::{choose::Choose, custom::Custom, dmenu::Dmenu, fzf::Fzf, rofi::Rofi, skim::Skim};
use crate::finder::{FinderStream, SelectionMode};

pub trait ExternalProgram: FinderStream + Send + Sync {
Expand Down
25 changes: 24 additions & 1 deletion clipcat-menu/src/finder/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ use tokio::io::AsyncWriteExt;

use self::{
builtin::BuiltinFinder,
external::{Custom, Dmenu, ExternalProgram, Fzf, Rofi, Skim},
external::{Choose, Custom, Dmenu, ExternalProgram, Fzf, Rofi, Skim},
};
pub use self::{error::FinderError, finder_stream::FinderStream};
use crate::config::Config;
Expand Down Expand Up @@ -41,15 +41,33 @@ pub enum FinderType {
#[serde(rename = "fzf")]
Fzf,

#[serde(rename = "choose")]
Choose,

#[serde(rename = "custom")]
Custom,
}

impl FinderType {
#[cfg(all(
unix,
not(any(
target_os = "macos",
target_os = "ios",
target_os = "android",
target_os = "emscripten"
))
))]
#[inline]
pub fn available_types() -> Vec<Self> {
vec![Self::Builtin, Self::Rofi, Self::Dmenu, Self::Skim, Self::Fzf, Self::Custom]
}

#[cfg(target_os = "macos")]
#[inline]
pub fn available_types() -> Vec<Self> {
vec![Self::Builtin, Self::Choose, Self::Skim, Self::Fzf, Self::Custom]
}
}

impl FromStr for FinderType {
Expand All @@ -60,6 +78,7 @@ impl FromStr for FinderType {
"builtin" => Ok(Self::Builtin),
"rofi" => Ok(Self::Rofi),
"dmenu" => Ok(Self::Dmenu),
"choose" => Ok(Self::Choose),
"skim" => Ok(Self::Skim),
"fzf" => Ok(Self::Fzf),
"custom" => Ok(Self::Custom),
Expand All @@ -74,6 +93,7 @@ impl fmt::Display for FinderType {
Self::Builtin => "builtin",
Self::Rofi => "rofi",
Self::Dmenu => "dmenu",
Self::Choose => "choose",
Self::Skim => "skim",
Self::Fzf => "fzf",
Self::Custom => "custom",
Expand All @@ -96,6 +116,9 @@ impl FinderRunner {
FinderType::Dmenu => {
Some(Box::new(Dmenu::from(config.dmenu.clone().unwrap_or_default())))
}
FinderType::Choose => {
Some(Box::new(Choose::from(config.choose.clone().unwrap_or_default())))
}
FinderType::Custom => Some(Box::new(Custom::from_config(
config.custom_finder.clone().unwrap_or_default(),
))),
Expand Down
5 changes: 5 additions & 0 deletions crates/clipboard/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,11 @@ clipcat-base = { path = "../base/" }
x11rb = { version = "0.13", features = ["xfixes"] }
wl-clipboard-rs = "0.8"

[target.'cfg(target_os = "macos")'.dependencies]
objc = "0.2"
objc_id = "0.1"
objc-foundation = "0.1"

[dev-dependencies]
tracing-subscriber = "0.3"

Expand Down
Loading

0 comments on commit f19760c

Please sign in to comment.