summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--Cargo.toml1
-rw-r--r--flake.lock94
-rw-r--r--flake.nix54
-rw-r--r--src/edit.rs136
-rw-r--r--src/lib.rs61
5 files changed, 292 insertions, 54 deletions
diff --git a/Cargo.toml b/Cargo.toml
index 6aca9fc..acc3138 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -15,6 +15,7 @@ edition = "2021"
[dependencies]
libc = "0.2"
+indoc = "1.0"
clap = { version = "2.33", optional = true }
anyhow = { version = "1.0", optional = true }
base64 = "0.13"
diff --git a/flake.lock b/flake.lock
new file mode 100644
index 0000000..f04c2d7
--- /dev/null
+++ b/flake.lock
@@ -0,0 +1,94 @@
+{
+ "nodes": {
+ "flake-utils": {
+ "locked": {
+ "lastModified": 1667395993,
+ "narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "flake-utils_2": {
+ "locked": {
+ "lastModified": 1659877975,
+ "narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
+ "type": "github"
+ },
+ "original": {
+ "owner": "numtide",
+ "repo": "flake-utils",
+ "type": "github"
+ }
+ },
+ "nixpkgs": {
+ "locked": {
+ "lastModified": 1670064435,
+ "narHash": "sha256-+ELoY30UN+Pl3Yn7RWRPabykwebsVK/kYE9JsIsUMxQ=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "61a8a98e6d557e6dd7ed0cdb54c3a3e3bbc5e25c",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixos-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "nixpkgs_2": {
+ "locked": {
+ "lastModified": 1665296151,
+ "narHash": "sha256-uOB0oxqxN9K7XGF1hcnY+PQnlQJ+3bP2vCn/+Ru/bbc=",
+ "owner": "NixOS",
+ "repo": "nixpkgs",
+ "rev": "14ccaaedd95a488dd7ae142757884d8e125b3363",
+ "type": "github"
+ },
+ "original": {
+ "owner": "NixOS",
+ "ref": "nixpkgs-unstable",
+ "repo": "nixpkgs",
+ "type": "github"
+ }
+ },
+ "root": {
+ "inputs": {
+ "flake-utils": "flake-utils",
+ "nixpkgs": "nixpkgs",
+ "rust-overlay": "rust-overlay"
+ }
+ },
+ "rust-overlay": {
+ "inputs": {
+ "flake-utils": "flake-utils_2",
+ "nixpkgs": "nixpkgs_2"
+ },
+ "locked": {
+ "lastModified": 1670207212,
+ "narHash": "sha256-uuKbbv0L+QoXiqO7METP9BihY0F7hJqGdKn7xDVfyFw=",
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "rev": "18823e511bc85ed27bfabe33cccecb389f9aa92d",
+ "type": "github"
+ },
+ "original": {
+ "owner": "oxalica",
+ "repo": "rust-overlay",
+ "type": "github"
+ }
+ }
+ },
+ "root": "root",
+ "version": 7
+}
diff --git a/flake.nix b/flake.nix
new file mode 100644
index 0000000..75077af
--- /dev/null
+++ b/flake.nix
@@ -0,0 +1,54 @@
+{
+ description = "vtcol development shell";
+
+ inputs = {
+ nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
+ rust-overlay.url = "github:oxalica/rust-overlay";
+ flake-utils.url = "github:numtide/flake-utils";
+ };
+
+ outputs = { self, nixpkgs, rust-overlay, flake-utils, ... }:
+ flake-utils.lib.eachDefaultSystem (system:
+ let
+ overlays = [ (import rust-overlay) ];
+ pkgs = import nixpkgs {
+ inherit system overlays;
+ };
+ in
+ with pkgs;
+ {
+ devShells.default = mkShell {
+ LD_LIBRARY_PATH = lib.makeLibraryPath [
+ libGL
+ libxkbcommon
+ wayland
+ xorg.libX11
+ xorg.libXcursor
+ xorg.libXi
+ xorg.libXrandr
+ ];
+
+ buildInputs = [
+ cmake
+ fontconfig
+ libglvnd
+ openssl
+ pkg-config
+ pkgconfig
+ rust-bin.beta.latest.default
+ xorg.libX11
+ xorg.libX11.dev
+ xorg.libXcursor
+ xorg.libXext
+ xorg.libXft
+ xorg.libXi
+ xorg.libXrandr
+ xorg.libXrender
+ xorg.libXt
+ xorg.xorgproto
+ xorg.xorgserver
+ ];
+ };
+ }
+ );
+}
diff --git a/src/edit.rs b/src/edit.rs
index a804def..f21cf73 100644
--- a/src/edit.rs
+++ b/src/edit.rs
@@ -1,6 +1,8 @@
use vtcol::{Palette, Rgb, Scheme};
-use std::{fmt, path::PathBuf, rc::Rc};
+use std::{fmt,
+ path::{Path, PathBuf},
+ rc::Rc};
use anyhow::{anyhow, Result};
@@ -143,12 +145,8 @@ slint::slint! {
input (k) => {
t.text = Aux.handle-command-buffer (k, t.text, cursor);
- if (t.text == "") {
- /* User backspaced her way to the left. */
- return true;
- }
-
- return false;
+ /* Buffer is empty if the user backspaced her way to the left. */
+ return t.text == "";
}
t := Text {
@@ -161,11 +159,8 @@ slint::slint! {
GuiEdit := Window {
property scheme-name <=> name.text;
- callback set-primary ([color]);
- callback set-secondary ([color]);
-
- set-primary (colors) => { primary-colors .colors = colors; }
- set-secondary (colors) => { secondary-colors.colors = colors; }
+ property <[color]> primary <=> primary-colors .colors;
+ property <[color]> secondary <=> secondary-colors.colors;
callback get-palette-color(int) -> color;
callback set-palette-color(int, color);
@@ -476,54 +471,67 @@ impl Edit
}
});
- gui.global::<Aux>().on_handle_command_buffer(|ev, text, _pos| {
- let text = match KeyInput::from(&ev) {
- KeyInput::Printable(s) => {
- let mut text = text.to_string();
- text.push_str(&s);
- text
- },
- KeyInput::Return => {
- match Command::try_from(text.as_str()) {
- Err(e) => {
- eprintln!("bad command [{}]: {}", text, e);
- String::new()
- },
- Ok(cmd) => {
- if let Err(e) = cmd.exec() {
- eprintln!(
- "error executing command [{}]: {}",
- text, e
- );
- }
- String::new()
+ {
+ let guiw = gui.as_weak();
+ gui.global::<Aux>().on_handle_command_buffer(move |ev, text, _pos| {
+ let text = match KeyInput::from(&ev) {
+ KeyInput::Printable(s) => {
+ let mut text = text.to_string();
+ text.push_str(&s);
+ text
+ },
+ KeyInput::Return => {
+ match Command::try_from(text.as_str()) {
+ Err(e) => {
+ eprintln!("bad command [{}]: {}", text, e);
+ String::new()
+ },
+ Ok(cmd) => {
+ use slint::Model;
+ let scheme_name =
+ guiw.unwrap().get_scheme_name().to_string();
+ let prim = guiw.unwrap().get_primary();
+ let secn = guiw.unwrap().get_secondary();
+ let pal = prim.iter().chain(secn.iter())
+ .collect::<Vec<Color>>();
+ let pal = Palette::from(pal.as_slice());
+ if let Err(e) = cmd
+ .exec(scheme_name.as_str(), pal)
+ {
+ eprintln!(
+ "error executing command [{}]: {}",
+ text, e
+ );
+ }
+ String::new()
+ },
+ }
+ /* The empty string signals to leave command mode. */
+ },
+ KeyInput::Backspace =>
+ match text.char_indices().next_back() {
+ Some((i, _)) => text[..i].into(),
+ None => text.to_string(),
},
- }
- /* The empty string signals to leave command mode. */
- },
- KeyInput::Backspace =>
- match text.char_indices().next_back() {
- Some((i, _)) => text[..i].into(),
- None => text.to_string(),
+ other => {
+ eprintln!(
+ "»»» command mode input: “{}”",
+ other.to_string()
+ );
+ text.to_string()
},
- other => {
- eprintln!(
- "»»» command mode input: “{}”",
- other.to_string()
- );
- text.to_string()
- },
- };
- eprintln!("»»» command buffer: “{}”", text);
- text.into()
- });
+ };
+ eprintln!("»»» command buffer: “{}”", text);
+ text.into()
+ });
+ }
if let Some(name) = name {
gui.set_scheme_name(name.into());
}
- gui.invoke_set_primary(primary.into());
- gui.invoke_set_secondary(secondary.into());
+ gui.set_primary(primary.into());
+ gui.set_secondary(secondary.into());
gui.run();
@@ -568,5 +576,25 @@ impl TryFrom<&str> for Command
impl Command
{
- fn exec(self) -> Result<()> { todo!("got command: {:?}", self) }
+ fn exec(self, name: &str, pal: Palette) -> Result<()>
+ {
+ match self {
+ Self::Noop => Ok(()),
+ Self::Save(None) => Self::save(&PathBuf::from(&name), pal),
+ Self::Save(Some(path)) => Self::save(&path, pal),
+ }
+ //todo!("got command: {:?}", self)
+ }
+
+ fn save(path: &Path, pal: Palette) -> Result<()>
+ {
+ use std::io::Write;
+
+ let mut f =
+ std::fs::OpenOptions::new().create(true).write(true).open(path)?;
+ let pal: String = pal.into();
+ f.write_all(pal.as_bytes()).map_err(|e| {
+ anyhow!("error saving Palette to file [{}]: {}", path.display(), e)
+ })
+ }
}
diff --git a/src/lib.rs b/src/lib.rs
index 021f25a..8ecc4a6 100644
--- a/src/lib.rs
+++ b/src/lib.rs
@@ -1125,6 +1125,67 @@ impl From<&RawPalette> for Palette
}
}
+#[cfg(feature = "gui")]
+impl From<&[slint::Color]> for Palette
+{
+ fn from(colors: &[slint::Color]) -> Self
+ {
+ let mut idx: usize = 0;
+ let mut pal: [u8; PALETTE_BYTES] = [0; PALETTE_BYTES];
+
+ for &col in colors.iter() {
+ pal[idx] = col.red();
+ pal[idx + 1] = col.green();
+ pal[idx + 2] = col.blue();
+ idx += 3;
+ }
+
+ Self(pal)
+ }
+}
+
+/** Convert palette to the default text format so it can be parsed as a scheme. */
+impl Into<String> for Palette
+{
+ fn into(self) -> String
+ {
+ let mut acc = String::with_capacity(16 * 10);
+ for i in 0..PALETTE_SIZE {
+ let idx = i * 3;
+ let (r, g, b) = (self.0[idx], self.0[idx + 1], self.0[idx + 2]);
+ acc.push_str(&format!("{}#{:02.x}{:02.x}{:02.x}\n", i, r, g, b));
+ }
+ acc
+ }
+}
+
+#[test]
+fn palette_dump_as_text()
+{
+ let pal = Palette::from(&SOLARIZED_COLORS_DARK);
+ let txt = indoc::indoc! { r#"
+ 0#002b36
+ 1#dc322f
+ 2#859900
+ 3#b58900
+ 4#268bd2
+ 5#d33682
+ 6#2aa198
+ 7#eee8d5
+ 8#002b36
+ 9#cb4b16
+ 10#586e75
+ 11#657b83
+ 12#839496
+ 13#6c71c4
+ 14#93a1a1
+ 15#fdf6e3
+ "#};
+
+ let pal: String = pal.into();
+ assert_eq!(pal, txt);
+}
+
pub struct PaletteIterator
{
pal: Palette,