mirror of
https://github.com/Noratrieb/clippyboard.git
synced 2026-01-14 09:55:04 +01:00
terrible nixos module
This commit is contained in:
parent
cead214aa1
commit
b2ff5b0763
8 changed files with 128 additions and 22 deletions
|
|
@ -3,6 +3,12 @@ name = "clippyboard"
|
|||
version = "0.1.0"
|
||||
edition = "2024"
|
||||
|
||||
[[bin]]
|
||||
name = "clippyboard-daemon"
|
||||
|
||||
[[bin]]
|
||||
name = "clippyboard-select"
|
||||
|
||||
[dependencies]
|
||||
ciborium = "0.2.2"
|
||||
dirs = "6.0.0"
|
||||
|
|
|
|||
|
|
@ -21,7 +21,9 @@
|
|||
];
|
||||
|
||||
postFixup = ''
|
||||
wrapProgram $out/bin/clippyboard \
|
||||
wrapProgram $out/bin/clippyboard-select \
|
||||
--suffix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath buildInputs}
|
||||
wrapProgram $out/bin/clippyboard-daemon \
|
||||
--suffix LD_LIBRARY_PATH : ${pkgs.lib.makeLibraryPath buildInputs}
|
||||
'';
|
||||
|
||||
|
|
|
|||
27
flake.lock
generated
Normal file
27
flake.lock
generated
Normal file
|
|
@ -0,0 +1,27 @@
|
|||
{
|
||||
"nodes": {
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1758029226,
|
||||
"narHash": "sha256-TjqVmbpoCqWywY9xIZLTf6ANFvDCXdctCjoYuYPYdMI=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "08b8f92ac6354983f5382124fef6006cade4a1c1",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixpkgs-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"nixpkgs": "nixpkgs"
|
||||
}
|
||||
}
|
||||
},
|
||||
"root": "root",
|
||||
"version": 7
|
||||
}
|
||||
47
flake.nix
Normal file
47
flake.nix
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
# warning: this flake is probably terrible, whatever
|
||||
{
|
||||
description = "clippyboard: a clipboard manager";
|
||||
|
||||
inputs = {
|
||||
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
|
||||
};
|
||||
|
||||
outputs = { nixpkgs, ... }:
|
||||
|
||||
let
|
||||
lib = nixpkgs.lib;
|
||||
clippyboard-package = ./default.nix;
|
||||
systems = lib.intersectLists lib.systems.flakeExposed lib.platforms.linux;
|
||||
forAllSystems = lib.genAttrs systems;
|
||||
in
|
||||
{
|
||||
packages = forAllSystems (system: { default = nixpkgs.${system}.callPackage clippyboard-package { }; });
|
||||
nixosModules.default = { lib, config, pkgs, ... }:
|
||||
let
|
||||
cfg = config.services.clippyboard;
|
||||
clippyboard = pkgs.callPackage clippyboard-package { };
|
||||
in
|
||||
{
|
||||
options.services.clippyboard = {
|
||||
enable = lib.mkEnableOption "Enable the clippyboard daemon and clippyboard program";
|
||||
};
|
||||
|
||||
config = lib.mkIf cfg.enable {
|
||||
nixpkgs.overlays = [
|
||||
(final: prev: {
|
||||
clipboard = clippyboard;
|
||||
})
|
||||
];
|
||||
systemd.user.services.clippyboard = {
|
||||
description = "a clipboard manager";
|
||||
wantedBy = [ "graphical-session.target" ];
|
||||
after = [ "graphical-session.target" ];
|
||||
serviceConfig = {
|
||||
ExecStart = lib.getExe' clippyboard "clippyboard-daemon";
|
||||
};
|
||||
};
|
||||
environment.systemPackages = [ clippyboard ];
|
||||
};
|
||||
};
|
||||
};
|
||||
}
|
||||
4
src/bin/clippyboard-daemon.rs
Normal file
4
src/bin/clippyboard-daemon.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
fn main() -> Result<(), eyre::Error> {
|
||||
let socket_path: std::path::PathBuf = clippyboard::socket_path()?;
|
||||
clippyboard::daemon::main(&socket_path)
|
||||
}
|
||||
4
src/bin/clippyboard-select.rs
Normal file
4
src/bin/clippyboard-select.rs
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
fn main() -> Result<(), eyre::Error> {
|
||||
let socket_path = clippyboard::socket_path()?;
|
||||
clippyboard::display::main(&socket_path)
|
||||
}
|
||||
|
|
@ -8,11 +8,16 @@ use rustix::event::PollFd;
|
|||
use rustix::event::PollFlags;
|
||||
use rustix::fs::OFlags;
|
||||
use std::collections::HashMap;
|
||||
use std::convert::Infallible;
|
||||
use std::io;
|
||||
use std::io::ErrorKind;
|
||||
use std::io::PipeReader;
|
||||
use std::io::{BufReader, BufWriter, PipeWriter, Read, Write};
|
||||
use std::os::fd::AsFd;
|
||||
use std::os::unix::net::{UnixListener, UnixStream};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::atomic::AtomicBool;
|
||||
use std::sync::atomic::Ordering;
|
||||
use std::sync::{Arc, Mutex, OnceLock, atomic::AtomicU64};
|
||||
use std::time::Duration;
|
||||
use std::time::SystemTime;
|
||||
|
|
@ -430,11 +435,24 @@ fn read_fd_into_history(
|
|||
}
|
||||
|
||||
pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
||||
let Err(err) = main_inner(socket_path);
|
||||
|
||||
if let Some(ioerr) = err.downcast_ref::<io::Error>()
|
||||
&& ioerr.kind() == ErrorKind::AddrInUse
|
||||
{
|
||||
// no cleanup
|
||||
return Err(err);
|
||||
}
|
||||
|
||||
cleanup(socket_path);
|
||||
Err(err)
|
||||
}
|
||||
|
||||
pub fn main_inner(socket_path: &PathBuf) -> eyre::Result<Infallible> {
|
||||
tracing_subscriber::fmt()
|
||||
.with_env_filter(EnvFilter::try_from_default_env().unwrap_or(EnvFilter::new("info")))
|
||||
.init();
|
||||
|
||||
let _ = std::fs::remove_file(&socket_path); // lol
|
||||
let socket = UnixListener::bind(&socket_path)
|
||||
.wrap_err_with(|| format!("binding path {}", socket_path.display()))?;
|
||||
|
||||
|
|
@ -481,9 +499,11 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
rustix::fs::fcntl_setfl(notify_write_recv.as_fd(), OFlags::NONBLOCK).expect("todo");
|
||||
rustix::fs::fcntl_setfl(conn.as_fd(), OFlags::NONBLOCK).expect("TODO");
|
||||
|
||||
let socket_path_clone = socket_path.to_owned();
|
||||
std::thread::spawn(move || {
|
||||
if let Err(err) = dispatch_wayland(queue, wl_state, notify_write_recv) {
|
||||
error!("error on Wayland thread: {err:?}");
|
||||
cleanup(&socket_path_clone);
|
||||
std::process::exit(1);
|
||||
}
|
||||
});
|
||||
|
|
@ -507,5 +527,13 @@ pub fn main(socket_path: &PathBuf) -> eyre::Result<()> {
|
|||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
unreachable!("socket.incoming will never return None")
|
||||
}
|
||||
|
||||
fn cleanup(socket_path: &PathBuf) {
|
||||
static HAS_DONE_CLEANUP: AtomicBool = AtomicBool::new(false);
|
||||
|
||||
if !HAS_DONE_CLEANUP.swap(true, Ordering::Relaxed) {
|
||||
let _ = std::fs::remove_file(&socket_path);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -1,9 +1,9 @@
|
|||
mod daemon;
|
||||
mod display;
|
||||
pub mod daemon;
|
||||
pub mod display;
|
||||
|
||||
use eyre::{OptionExt, bail};
|
||||
use eyre::OptionExt;
|
||||
use serde::{Deserialize, Deserializer, Serialize, Serializer};
|
||||
use std::sync::Arc;
|
||||
use std::{path::PathBuf, sync::Arc};
|
||||
|
||||
const MAX_ENTRY_SIZE: u64 = 50_000_000;
|
||||
const MAX_HISTORY_BYTE_SIZE: usize = 100_000_000;
|
||||
|
|
@ -33,20 +33,8 @@ const MESSAGE_READ: u8 = 1;
|
|||
/// Argument: One u64-bit LE value, the ID
|
||||
const MESSAGE_COPY: u8 = 2;
|
||||
|
||||
fn main() -> eyre::Result<()> {
|
||||
let Some(mode) = std::env::args().nth(1) else {
|
||||
bail!("missing mode");
|
||||
};
|
||||
|
||||
let socket_path = dirs::runtime_dir()
|
||||
pub fn socket_path() -> eyre::Result<PathBuf> {
|
||||
Ok(dirs::runtime_dir()
|
||||
.ok_or_eyre("missing XDG_RUNTIME_DIR")?
|
||||
.join("clippyboard.sock");
|
||||
|
||||
match mode.as_str() {
|
||||
"daemon" => daemon::main(&socket_path)?,
|
||||
"display" => display::main(&socket_path)?,
|
||||
_ => panic!("invalid mode, supported: daemon, display"),
|
||||
}
|
||||
|
||||
Ok(())
|
||||
.join("clippyboard.sock"))
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue