summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-05 17:22:10 +0100
committerSakarias Johansson <sakarias.johansson@goodbyekansas.com>2023-01-05 17:22:10 +0100
commitcf7bd1aec7e9908f80bfc014fc53a1144e17ccb5 (patch)
treed37492001d250f7dc7a1584415181ad443f62d8a
downloadracer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.tar.gz
racer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.tar.xz
racer-tracer-cf7bd1aec7e9908f80bfc014fc53a1144e17ccb5.zip
Initial commit 🎉
-rw-r--r--.gitignore1
-rw-r--r--LICENSE21
-rw-r--r--default.nix66
-rw-r--r--nix/sources.json38
-rw-r--r--nix/sources.nix174
-rw-r--r--racer-tracer/.gitignore10
-rw-r--r--racer-tracer/.projectile0
-rw-r--r--racer-tracer/Cargo.toml10
-rw-r--r--racer-tracer/src/error.rs26
-rw-r--r--racer-tracer/src/main.rs78
10 files changed, 424 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..b428354
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1 @@
+/release*
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..65b9f32
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,21 @@
+MIT License
+
+Copyright (c) 2023 Sakarias Johansson
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all
+copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
+SOFTWARE.
diff --git a/default.nix b/default.nix
new file mode 100644
index 0000000..fe76061
--- /dev/null
+++ b/default.nix
@@ -0,0 +1,66 @@
+let
+ sources = import ./nix/sources.nix;
+ nixpkgs = with
+ {
+ overlay = _: pkgs:
+ {
+ niv = (import sources.niv { }).niv;
+ };
+ };
+ import sources.nixpkgs
+ {
+ overlays = [ overlay (import sources.rust) ];
+ config = { };
+ };
+
+ rustBin = nixpkgs.rust-bin.stable."1.65.0".rust;
+
+ # rust-analyzer cannot handle symlinks
+ # so we need to create a derivation with the
+ # correct rust source without symlinks
+ rustSrcNoSymlinks = nixpkgs.stdenv.mkDerivation {
+ name = "rust-src-no-symlinks";
+
+ rustWithSrc = (rustBin.override {
+ extensions = [ "rust-src" ];
+ });
+ rust = rustBin;
+
+ builder = builtins.toFile "builder.sh" ''
+ source $stdenv/setup
+ mkdir -p $out
+ cp -r -L $rustWithSrc/lib/rustlib/src/rust/library/. $out/
+ '';
+ };
+in
+nixpkgs.stdenv.mkDerivation {
+ name = "racer-tracer";
+ src = nixpkgs.nix-gitignore.gitignoreSource [] ./racer-tracer;
+ nativeBuildInputs = [ rustBin nixpkgs.cacert nixpkgs.xorg.libX11 ];
+ configurePhase = ''
+ export CARGO_HOME=$PWD
+ '';
+
+ buildPhase = ''
+ cargo build --release
+ '';
+
+ checkPhase = ''
+ cargo fmt -- --check
+ cargo clippy
+ cargo test
+ '';
+
+ doCheck = true;
+
+ installPhase = ''
+ mkdir -p $out/bin
+ find target/release -executable -type f -exec cp {} $out/bin \;
+ '';
+
+ shellHook = ''
+ export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:${nixpkgs.lib.makeLibraryPath [ nixpkgs.xorg.libX11 nixpkgs.xorg.libXcursor ] }
+ #export LD_LIBRARY_PATH=$LD_LIBRARY_PATH:/usr/lib64/
+ export RUST_SRC_PATH=${rustSrcNoSymlinks}
+ '';
+}
diff --git a/nix/sources.json b/nix/sources.json
new file mode 100644
index 0000000..de0bdb3
--- /dev/null
+++ b/nix/sources.json
@@ -0,0 +1,38 @@
+{
+ "niv": {
+ "branch": "master",
+ "description": "Easy dependency management for Nix projects",
+ "homepage": "https://github.com/nmattia/niv",
+ "owner": "nmattia",
+ "repo": "niv",
+ "rev": "351d8bc316bf901a81885bab5f52687ec8ccab6e",
+ "sha256": "1yzhz7ihkh6p2sxhp3amqfbmm2yqzaadqqii1xijymvl8alw5rrr",
+ "type": "tarball",
+ "url": "https://github.com/nmattia/niv/archive/351d8bc316bf901a81885bab5f52687ec8ccab6e.tar.gz",
+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+ },
+ "nixpkgs": {
+ "branch": "release-21.11",
+ "description": "Nix Packages collection",
+ "homepage": "",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "a7ecde854aee5c4c7cd6177f54a99d2c1ff28a31",
+ "sha256": "sha256:162dywda2dvfj1248afxc45kcrg83appjd0nmdb541hl7rnncf02",
+ "type": "tarball",
+ "url": "https://github.com/NixOS/nixpkgs/archive/a7ecde854aee5c4c7cd6177f54a99d2c1ff28a31.tar.gz",
+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+ },
+ "rust": {
+ "branch": "master",
+ "description": "Pure and reproducible nix overlay of binary distributed rust toolchains",
+ "homepage": "",
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "9767af967a0becaa3bb79eeda838dbf81295eb62",
+ "sha256": "00jbn8c8mzhf73n8ny2j7y44m181v0vip1qjhc2qkvdv6v1wnhs6",
+ "type": "tarball",
+ "url": "https://github.com/oxalica/rust-overlay/archive/9767af967a0becaa3bb79eeda838dbf81295eb62.tar.gz",
+ "url_template": "https://github.com/<owner>/<repo>/archive/<rev>.tar.gz"
+ }
+}
diff --git a/nix/sources.nix b/nix/sources.nix
new file mode 100644
index 0000000..1938409
--- /dev/null
+++ b/nix/sources.nix
@@ -0,0 +1,174 @@
+# This file has been generated by Niv.
+
+let
+
+ #
+ # The fetchers. fetch_<type> fetches specs of type <type>.
+ #
+
+ fetch_file = pkgs: name: spec:
+ let
+ name' = sanitizeName name + "-src";
+ in
+ if spec.builtin or true then
+ builtins_fetchurl { inherit (spec) url sha256; name = name'; }
+ else
+ pkgs.fetchurl { inherit (spec) url sha256; name = name'; };
+
+ fetch_tarball = pkgs: name: spec:
+ let
+ name' = sanitizeName name + "-src";
+ in
+ if spec.builtin or true then
+ builtins_fetchTarball { name = name'; inherit (spec) url sha256; }
+ else
+ pkgs.fetchzip { name = name'; inherit (spec) url sha256; };
+
+ fetch_git = name: spec:
+ let
+ ref =
+ if spec ? ref then spec.ref else
+ if spec ? branch then "refs/heads/${spec.branch}" else
+ if spec ? tag then "refs/tags/${spec.tag}" else
+ abort "In git source '${name}': Please specify `ref`, `tag` or `branch`!";
+ in
+ builtins.fetchGit { url = spec.repo; inherit (spec) rev; inherit ref; };
+
+ fetch_local = spec: spec.path;
+
+ fetch_builtin-tarball = name: throw
+ ''[${name}] The niv type "builtin-tarball" is deprecated. You should instead use `builtin = true`.
+ $ niv modify ${name} -a type=tarball -a builtin=true'';
+
+ fetch_builtin-url = name: throw
+ ''[${name}] The niv type "builtin-url" will soon be deprecated. You should instead use `builtin = true`.
+ $ niv modify ${name} -a type=file -a builtin=true'';
+
+ #
+ # Various helpers
+ #
+
+ # https://github.com/NixOS/nixpkgs/pull/83241/files#diff-c6f540a4f3bfa4b0e8b6bafd4cd54e8bR695
+ sanitizeName = name:
+ (
+ concatMapStrings (s: if builtins.isList s then "-" else s)
+ (
+ builtins.split "[^[:alnum:]+._?=-]+"
+ ((x: builtins.elemAt (builtins.match "\\.*(.*)" x) 0) name)
+ )
+ );
+
+ # The set of packages used when specs are fetched using non-builtins.
+ mkPkgs = sources: system:
+ let
+ sourcesNixpkgs =
+ import (builtins_fetchTarball { inherit (sources.nixpkgs) url sha256; }) { inherit system; };
+ hasNixpkgsPath = builtins.any (x: x.prefix == "nixpkgs") builtins.nixPath;
+ hasThisAsNixpkgsPath = <nixpkgs> == ./.;
+ in
+ if builtins.hasAttr "nixpkgs" sources
+ then sourcesNixpkgs
+ else if hasNixpkgsPath && ! hasThisAsNixpkgsPath then
+ import <nixpkgs> {}
+ else
+ abort
+ ''
+ Please specify either <nixpkgs> (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 name spec
+ else if spec.type == "tarball" then fetch_tarball pkgs name spec
+ else if spec.type == "git" then fetch_git name spec
+ else if spec.type == "local" then fetch_local spec
+ else if spec.type == "builtin-tarball" then fetch_builtin-tarball name
+ else if spec.type == "builtin-url" then fetch_builtin-url name
+ else
+ abort "ERROR: niv spec ${name} has unknown type ${builtins.toJSON spec.type}";
+
+ # If the environment variable NIV_OVERRIDE_${name} is set, then use
+ # the path directly as opposed to the fetched source.
+ replace = name: drv:
+ let
+ saneName = stringAsChars (c: if isNull (builtins.match "[a-zA-Z0-9]" c) then "_" else c) name;
+ ersatz = builtins.getEnv "NIV_OVERRIDE_${saneName}";
+ in
+ if ersatz == "" then drv else
+ # this turns the string into an actual Nix path (for both absolute and
+ # relative paths)
+ if builtins.substring 0 1 ersatz == "/" then /. + ersatz else /. + builtins.getEnv "PWD" + "/${ersatz}";
+
+ # 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))
+ );
+
+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/lists.nix#L295
+ range = first: last: if first > last then [] else builtins.genList (n: first + n) (last - first + 1);
+
+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L257
+ stringToCharacters = s: map (p: builtins.substring p 1 s) (range 0 (builtins.stringLength s - 1));
+
+ # https://github.com/NixOS/nixpkgs/blob/0258808f5744ca980b9a1f24fe0b1e6f0fecee9c/lib/strings.nix#L269
+ stringAsChars = f: s: concatStrings (map f (stringToCharacters s));
+ concatMapStrings = f: list: concatStrings (map f list);
+ concatStrings = builtins.concatStringsSep "";
+
+ # https://github.com/NixOS/nixpkgs/blob/8a9f58a375c401b96da862d969f66429def1d118/lib/attrsets.nix#L331
+ optionalAttrs = cond: as: if cond then as else {};
+
+ # fetchTarball version that is compatible between all the versions of Nix
+ builtins_fetchTarball = { url, name ? null, sha256 }@attrs:
+ let
+ inherit (builtins) lessThan nixVersion fetchTarball;
+ in
+ if lessThan nixVersion "1.12" then
+ fetchTarball ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
+ else
+ fetchTarball attrs;
+
+ # fetchurl version that is compatible between all the versions of Nix
+ builtins_fetchurl = { url, name ? null, sha256 }@attrs:
+ let
+ inherit (builtins) lessThan nixVersion fetchurl;
+ in
+ if lessThan nixVersion "1.12" then
+ fetchurl ({ inherit url; } // (optionalAttrs (!isNull name) { inherit name; }))
+ 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 = replace name (fetch config.pkgs name spec); }
+ ) config.sources;
+
+ # The "config" used by the fetchers
+ mkConfig =
+ { sourcesFile ? if builtins.pathExists ./sources.json then ./sources.json else null
+ , sources ? if isNull sourcesFile then {} else builtins.fromJSON (builtins.readFile sourcesFile)
+ , system ? builtins.currentSystem
+ , pkgs ? mkPkgs sources system
+ }: 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/racer-tracer/.gitignore b/racer-tracer/.gitignore
new file mode 100644
index 0000000..767dae2
--- /dev/null
+++ b/racer-tracer/.gitignore
@@ -0,0 +1,10 @@
+# Generated by Cargo
+# will have compiled files and executables
+target/
+
+# Remove Cargo.lock from gitignore if creating an executable, leave it for libraries
+# More information here https://doc.rust-lang.org/cargo/guide/cargo-toml-vs-cargo-lock.html
+Cargo.lock
+
+# These are backup files generated by rustfmt
+**/*.rs.bk
diff --git a/racer-tracer/.projectile b/racer-tracer/.projectile
new file mode 100644
index 0000000..e69de29
--- /dev/null
+++ b/racer-tracer/.projectile
diff --git a/racer-tracer/Cargo.toml b/racer-tracer/Cargo.toml
new file mode 100644
index 0000000..e764f79
--- /dev/null
+++ b/racer-tracer/Cargo.toml
@@ -0,0 +1,10 @@
+[package]
+name = "racer-tracer"
+version = "0.1.0"
+authors = ["Sakarias Johansson <sakarias.johansson@goodbyekansas.com>"]
+edition = "2021"
+
+[dependencies]
+minifb = "0.23"
+tokio = { version = "1.14.0", features = ["macros", "rt", "rt-multi-thread"] }
+thiserror = "1"
diff --git a/racer-tracer/src/error.rs b/racer-tracer/src/error.rs
new file mode 100644
index 0000000..f581b08
--- /dev/null
+++ b/racer-tracer/src/error.rs
@@ -0,0 +1,26 @@
+use thiserror::Error;
+
+#[derive(Error, Debug)]
+pub enum TracerError {
+ #[error("Unknown error: {message}")]
+ Unknown { message: String, exit_code: i32 },
+
+ #[error("Failed to create window: {0}")]
+ FailedToCreateWindow(String),
+
+ #[error("Failed to update window: {0}")]
+ FailedToUpdateWindow(String),
+}
+
+impl From<TracerError> for i32 {
+ fn from(tracer_error: TracerError) -> Self {
+ match tracer_error {
+ TracerError::Unknown {
+ message: _,
+ exit_code,
+ } => exit_code,
+ TracerError::FailedToCreateWindow(_) => 2,
+ TracerError::FailedToUpdateWindow(_) => 3,
+ }
+ }
+}
diff --git a/racer-tracer/src/main.rs b/racer-tracer/src/main.rs
new file mode 100644
index 0000000..959ea0a
--- /dev/null
+++ b/racer-tracer/src/main.rs
@@ -0,0 +1,78 @@
+#[macro_use]
+mod error;
+
+use minifb::{Key, Window, WindowOptions};
+
+fn hsv_to_rgb(H: f64, S: f64, V: f64) -> u32 {
+ let s: f64 = S / 100.0;
+ let v: f64 = V / 100.0;
+ let C: f64 = s * v;
+ let mut A: f64 = H / 60.0;
+ A %= 2.0f64;
+ let X: f64 = C * (1f64 - (A - 1f64).abs());
+ let m: f64 = v - C;
+
+ let mut r: f64;
+ let mut g: f64;
+ let mut b: f64;
+ if H >= 0.0 && H < 60.0 {
+ r = C;
+ g = X;
+ b = 0.0;
+ } else if H >= 60.0 && H < 120.0 {
+ r = X;
+ g = C;
+ b = 0.0;
+ } else if H >= 120.0 && H < 180.0 {
+ r = 0.0;
+ g = C;
+ b = X;
+ } else if H >= 180.0 && H < 240.0 {
+ r = 0.0;
+ g = X;
+ b = C;
+ } else if H >= 240.0 && H < 300.0 {
+ r = X;
+ g = 0.0;
+ b = C;
+ } else {
+ r = C;
+ g = 0.0;
+ b = X;
+ }
+
+ let red: u32 = ((r + m) * 255.0) as u32;
+ let green: u32 = ((g + m) * 255.0) as u32;
+ let blue: u32 = ((b + m) * 255.0) as u32;
+ ((red as u32) << 16) | ((green as u32) << 8) | blue as u32
+}
+
+async fn run(width: usize, height: usize) -> Result<(), error::TracerError> {
+ let mut screen_buffer: Vec<u32> = vec![0; width * height];
+ let mut window = Window::new("racer-tracer", width, height, WindowOptions::default())
+ .expect("Unable to create window");
+ window.limit_update_rate(Some(std::time::Duration::from_micros(16600)));
+
+ let mut count = 1;
+ while window.is_open() && !window.is_key_down(Key::Escape) {
+ count = (count + 1) % 360;
+ let color = hsv_to_rgb(count as f64, 100.0, 100.0);
+ for i in screen_buffer.iter_mut() {
+ *i = color;
+ }
+
+ window
+ .update_with_buffer(&screen_buffer, width, height)
+ .map_err(|e| error::TracerError::FailedToUpdateWindow(e.to_string()))?;
+ }
+
+ Ok(())
+}
+
+#[tokio::main]
+async fn main() {
+ if let Err(e) = run(640, 480).await {
+ eprintln!("{}", e);
+ std::process::exit(e.into())
+ }
+}