From 6a58a1daac6944c30c67aa4d4bcf6971beffdeb6 Mon Sep 17 00:00:00 2001 From: Christine Dodrill Date: Mon, 6 Apr 2020 21:09:09 -0400 Subject: [PATCH] initial commit --- .envrc | 1 + .gitignore | 1 + Cargo.lock | 106 +++++++++++++++++++++++++++++++++++++ Cargo.toml | 14 +++++ nix/sources.json | 26 +++++++++ nix/sources.nix | 134 +++++++++++++++++++++++++++++++++++++++++++++++ shell.nix | 15 ++++++ src/main.rs | 68 ++++++++++++++++++++++++ src/xsetroot.rs | 53 +++++++++++++++++++ 9 files changed, 418 insertions(+) create mode 100644 .envrc create mode 100644 .gitignore create mode 100644 Cargo.lock create mode 100644 Cargo.toml create mode 100644 nix/sources.json create mode 100644 nix/sources.nix create mode 100644 shell.nix create mode 100644 src/main.rs create mode 100644 src/xsetroot.rs diff --git a/.envrc b/.envrc new file mode 100644 index 0000000..be81fed --- /dev/null +++ b/.envrc @@ -0,0 +1 @@ +eval "$(lorri direnv)" \ No newline at end of file diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..ea8c4bf --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/target diff --git a/Cargo.lock b/Cargo.lock new file mode 100644 index 0000000..59497b5 --- /dev/null +++ b/Cargo.lock @@ -0,0 +1,106 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +[[package]] +name = "autocfg" +version = "1.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8aac770f1885fd7e387acedd76065302551364496e46b3dd00860b2f8359b9d" + +[[package]] +name = "cabytcini" +version = "0.1.0" +dependencies = [ + "chrono", + "x11", +] + +[[package]] +name = "chrono" +version = "0.4.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "80094f509cf8b5ae86a4966a39b3ff66cd7e2a3e594accec3743ff3fabeab5b2" +dependencies = [ + "num-integer", + "num-traits", + "time", +] + +[[package]] +name = "libc" +version = "0.2.68" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dea0c0405123bba743ee3f91f49b1c7cfb684eef0da0a50110f758ccf24cdff0" + +[[package]] +name = "num-integer" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3f6ea62e9d81a77cd3ee9a2a5b9b609447857f3d358704331e4ef39eb247fcba" +dependencies = [ + "autocfg", + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c62be47e61d1842b9170f0fdeec8eba98e60e90e5446449a0545e5152acd7096" +dependencies = [ + "autocfg", +] + +[[package]] +name = "pkg-config" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05da548ad6865900e60eaba7f589cc0783590a92e940c26953ff81ddbab2d677" + +[[package]] +name = "redox_syscall" +version = "0.1.56" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2439c63f3f6139d1b57529d16bc3b8bb855230c8efcc5d3a896c8bea7c3b1e84" + +[[package]] +name = "time" +version = "0.1.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db8dcfca086c1143c9270ac42a2bbd8a7ee477b78ac8e45b19abfb0cbede4b6f" +dependencies = [ + "libc", + "redox_syscall", + "winapi", +] + +[[package]] +name = "winapi" +version = "0.3.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "x11" +version = "2.18.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "77ecd092546cb16f25783a5451538e73afc8d32e242648d54f4ae5459ba1e773" +dependencies = [ + "libc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml new file mode 100644 index 0000000..b3b44aa --- /dev/null +++ b/Cargo.toml @@ -0,0 +1,14 @@ +[package] +name = "cabytcini" +version = "0.1.0" +authors = ["Christine Dodrill "] +edition = "2018" + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +chrono = "0.4" + +[dependencies.x11] +features = ["xlib"] +version = "2.18.2" diff --git a/nix/sources.json b/nix/sources.json new file mode 100644 index 0000000..ca6cc23 --- /dev/null +++ b/nix/sources.json @@ -0,0 +1,26 @@ +{ + "niv": { + "branch": "master", + "description": "Easy dependency management for Nix projects", + "homepage": "https://github.com/nmattia/niv", + "owner": "nmattia", + "repo": "niv", + "rev": "f73bf8d584148677b01859677a63191c31911eae", + "sha256": "0jlmrx633jvqrqlyhlzpvdrnim128gc81q5psz2lpp2af8p8q9qs", + "type": "tarball", + "url": "https://github.com/nmattia/niv/archive/f73bf8d584148677b01859677a63191c31911eae.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + }, + "nixpkgs": { + "branch": "nixos-20.03", + "description": "A read-only mirror of NixOS/nixpkgs tracking the released channels. Send issues and PRs to", + "homepage": "https://github.com/NixOS/nixpkgs", + "owner": "NixOS", + "repo": "nixpkgs-channels", + "rev": "0bb35152be895abfd1fc743b42f1c4e56ae71906", + "sha256": "0mydmhr1fm5l0p668wx5wlk3six7k3n56sz41fv0h9zms0lqszf9", + "type": "tarball", + "url": "https://github.com/NixOS/nixpkgs-channels/archive/0bb35152be895abfd1fc743b42f1c4e56ae71906.tar.gz", + "url_template": "https://github.com///archive/.tar.gz" + } +} diff --git a/nix/sources.nix b/nix/sources.nix new file mode 100644 index 0000000..8a725cb --- /dev/null +++ b/nix/sources.nix @@ -0,0 +1,134 @@ +# This file has been generated by Niv. + +let + + # + # The fetchers. fetch_ fetches specs of type . + # + + fetch_file = pkgs: spec: + if spec.builtin or true then + builtins_fetchurl { inherit (spec) url sha256; } + else + pkgs.fetchurl { inherit (spec) url sha256; }; + + fetch_tarball = pkgs: spec: + if spec.builtin or true then + builtins_fetchTarball { inherit (spec) url sha256; } + else + pkgs.fetchzip { inherit (spec) url sha256; }; + + fetch_git = spec: + builtins.fetchGit { url = spec.repo; inherit (spec) rev ref; }; + + fetch_builtin-tarball = spec: + builtins.trace + '' + WARNING: + The niv type "builtin-tarball" will soon be deprecated. You should + instead use `builtin = true`. + + $ niv modify -a type=tarball -a builtin=true + '' + builtins_fetchTarball { inherit (spec) url sha256; }; + + fetch_builtin-url = spec: + builtins.trace + '' + WARNING: + The niv type "builtin-url" will soon be deprecated. You should + instead use `builtin = true`. + + $ niv modify -a type=file -a builtin=true + '' + (builtins_fetchurl { inherit (spec) url sha256; }); + + # + # Various helpers + # + + # The set of packages used when specs are fetched using non-builtins. + mkPkgs = sources: + let + sourcesNixpkgs = + import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) {}; + hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath; + hasThisAsNixpkgsPath = == ./.; + in + if builtins.hasAttr "nixpkgs" sources + then sourcesNixpkgs + else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then + import {} + else + abort + '' + Please specify either (through -I or NIX_PATH=nixpkgs=...) or + add a package called "nixpkgs" to your sources.json. + ''; + + # The actual fetching function. + fetch = pkgs: name: spec: + + if ! builtins.hasAttr "type" spec then + abort "ERROR: niv spec ${name} does not have a 'type' attribute" + else if spec.type == "file" then fetch_file pkgs spec + else if spec.type == "tarball" then fetch_tarball pkgs spec + else if spec.type == "git" then fetch_git spec + else if spec.type == "builtin-tarball" then fetch_builtin-tarball spec + else if spec.type == "builtin-url" then fetch_builtin-url spec + else + abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}"; + + # Ports of functions for older nix versions + + # a Nix version of mapAttrs if the built-in doesn't exist + mapAttrs = builtins.mapAttrs or ( + f: set: with builtins; + listToAttrs (map (attr: { name = attr; value = f attr set.${attr}; }) (attrNames set)) + ); + + # fetchTarball version that is compatible between all the versions of Nix + builtins_fetchTarball = { url, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchTarball; + in + if lessThan nixVersion "1.12" then + fetchTarball { inherit url; } + else + fetchTarball attrs; + + # fetchurl version that is compatible between all the versions of Nix + builtins_fetchurl = { url, sha256 }@attrs: + let + inherit (builtins) lessThan nixVersion fetchurl; + in + if lessThan nixVersion "1.12" then + fetchurl { inherit url; } + else + fetchurl attrs; + + # Create the final "sources" from the config + mkSources = config: + mapAttrs ( + name: spec: + if builtins.hasAttr "outPath" spec + then abort + "The values in sources.json should not have an 'outPath' attribute" + else + spec // { outPath = fetch config.pkgs name spec; } + ) config.sources; + + # The "config" used by the fetchers + mkConfig = + { sourcesFile ? ./sources.json + , sources ? builtins.fromJSON (builtins.readFile sourcesFile) + , pkgs ? mkPkgs sources + }: rec { + # The sources, i.e. the attribute set of spec name to spec + inherit sources; + + # The "pkgs" (evaluated nixpkgs) to use for e.g. non-builtin fetchers + inherit pkgs; + }; +in +mkSources (mkConfig {}) // { __functor = _: settings: mkSources (mkConfig settings); } diff --git a/shell.nix b/shell.nix new file mode 100644 index 0000000..9c34d12 --- /dev/null +++ b/shell.nix @@ -0,0 +1,15 @@ +let + sources = import ./nix/sources.nix; + pkgs = import sources.nixpkgs { }; +in pkgs.mkShell { + buildInputs = with pkgs; [ + cargo + rls + rustc + rustfmt + + # dev dependencies + xorg.libX11 + pkg-config + ]; +} diff --git a/src/main.rs b/src/main.rs new file mode 100644 index 0000000..441b9eb --- /dev/null +++ b/src/main.rs @@ -0,0 +1,68 @@ +mod xsetroot; + +use chrono::prelude::*; +use std::fmt; +use std::io::prelude::*; +use std::io::BufReader; +use std::sync::{Arc, Mutex}; +use std::thread; +use std::os::unix::net::{UnixStream, UnixListener}; +use xsetroot::XSetRoot; + +type MTState = Arc>; + +fn handle_client(stream: UnixStream, st: MTState) { + let mut rdr = BufReader::new(&stream); + let mut msg = String::new(); + let _ = rdr.read_line(&mut msg); + let _ = write!(&stream, "OK"); + + let mut data = st.lock().unwrap(); + data.msg = msg; + data.show(); +} + +fn main() -> std::io::Result::<()> { + let mut st: State = State::init(); + st.msg = "coi rodo .ui.".to_string(); + st.show(); + let mtst = Arc::new(Mutex::new(st)); + + let listener = UnixListener::bind("/home/cadey/tmp/cabytcini.sock")?; + for stream in listener.incoming() { + match stream { + Ok(stream) => { + thread::spawn(|| handle_client(stream, mtst.clone())); + }, + Err(err) => { + break; + }, + } + } + + Ok(()) +} + +struct State { + msg: String, +} + +impl fmt::Display for State { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + write!(f, "{}", self.msg) + } +} + +impl State { + fn init() -> State { + State { + msg: "".to_string(), + } + } + + fn show(&self) { + let now = Local::now(); + let xsr = XSetRoot::init(); + xsr.render(format!("{} | {}", self, now.format("%H:%M M%m %-d %a"))); + } +} diff --git a/src/xsetroot.rs b/src/xsetroot.rs new file mode 100644 index 0000000..7e153ad --- /dev/null +++ b/src/xsetroot.rs @@ -0,0 +1,53 @@ +#![allow(unsafe_code)] + +use std::ffi::CString; +use std::os::raw::c_char; +use std::ptr; +use x11::xlib; + +pub(crate) struct XSetRoot { + display: *mut xlib::Display, + root_window: xlib::Window, +} + +impl XSetRoot { + pub(crate) fn init() -> Self { + unsafe { + let display = xlib::XOpenDisplay(ptr::null()); + + if display.is_null() { + panic!("cannot open display"); + } + + let screen = xlib::XDefaultScreen(display); + let root_window = xlib::XRootWindow(display, screen); + + Self { + display, + root_window, + } + } + } + + pub(crate) fn render(&self, text: String) { + let status_c = CString::new(text).expect("status text could not be converted to CString"); + + unsafe { + xlib::XStoreName( + self.display, + self.root_window, + status_c.as_ptr() as *mut c_char, + ); + + xlib::XFlush(self.display); + } + } +} + +impl Drop for XSetRoot { + fn drop(&mut self) { + unsafe { + xlib::XCloseDisplay(self.display); + } + } +}