From 9d9330d6bc700b3252f0a2107412ce39f0b89dd6 Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Tue, 7 Apr 2026 13:49:12 +0200 Subject: [PATCH 1/6] fix: cross-platform compatibility for Windows support - Use directories::BaseDirs for config path fallback instead of hardcoded Unix path - Default to notepad on Windows instead of vi for editor commands - Skip +N line argument for notepad in todo edit (notepad doesn't support it) --- src/cli/commands/edit.rs | 8 +++++++- src/cli/commands/new.rs | 8 +++++++- src/cli/commands/todo.rs | 18 ++++++++++++------ src/config.rs | 4 +++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/cli/commands/edit.rs b/src/cli/commands/edit.rs index a8761f3..4c15017 100644 --- a/src/cli/commands/edit.rs +++ b/src/cli/commands/edit.rs @@ -67,7 +67,13 @@ pub fn run(number: i32) -> Result<(), StreamdError> { }; if let Some(file_path) = sorted_shards[selected_index].location.get("file") { - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); Command::new(&editor).arg(file_path).status()?; } diff --git a/src/cli/commands/new.rs b/src/cli/commands/new.rs index de7d351..5c3eecb 100644 --- a/src/cli/commands/new.rs +++ b/src/cli/commands/new.rs @@ -24,7 +24,13 @@ pub fn run() -> Result<(), StreamdError> { drop(file); // Open in editor - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); let status = Command::new(&editor).arg(&preliminary_path).status()?; if !status.success() { diff --git a/src/cli/commands/todo.rs b/src/cli/commands/todo.rs index 17bfba2..e54d1e2 100644 --- a/src/cli/commands/todo.rs +++ b/src/cli/commands/todo.rs @@ -92,13 +92,19 @@ pub fn run_edit(number: usize) -> Result<(), StreamdError> { .get("file") .ok_or(StreamdError::MissingFilePath)?; - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); - let line_arg = format!("+{}", task.start_line); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); - let status = Command::new(&editor) - .arg(&line_arg) - .arg(file_path) - .status()?; + let mut cmd = Command::new(&editor); + if !editor.to_lowercase().contains("notepad") { + cmd.arg(format!("+{}", task.start_line)); + } + let status = cmd.arg(file_path).status()?; if !status.success() { return Err(StreamdError::IoError(std::io::Error::other( diff --git a/src/config.rs b/src/config.rs index c828ba9..417e8f0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -37,8 +37,10 @@ impl Settings { fn config_path() -> PathBuf { if let Some(proj_dirs) = ProjectDirs::from("", "", "streamd") { proj_dirs.config_dir().join("config.toml") + } else if let Some(base_dirs) = directories::BaseDirs::new() { + base_dirs.config_dir().join("streamd").join("config.toml") } else { - PathBuf::from("~/.config/streamd/config.toml") + PathBuf::from("streamd_config.toml") } } } From dbc68da5c9f5e9469d807a287f56e7b6c7d71335 Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Tue, 7 Apr 2026 13:49:45 +0200 Subject: [PATCH 2/6] feat: add Windows cross-compilation and release artifacts - Add mkWindowsCraneLib using x86_64-pc-windows-gnu target - Add mkStreamdWindows using mingw-w64 toolchain for cross-compilation - Export streamd-windows package from flake - Add Windows build step and .exe artifact to release workflow --- .forgejo/workflows/release.yml | 5 +++++ flake.nix | 35 +++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 7c93504..bef91f5 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -49,12 +49,17 @@ jobs: if: steps.version.outputs.SKIP != 'true' run: nix build .#streamd-musl -o result-musl + - name: Build Windows binary + if: steps.version.outputs.SKIP != 'true' + run: nix build .#streamd-windows -o result-windows + - name: Prepare release artifacts if: steps.version.outputs.SKIP != 'true' run: | mkdir -p release cp result-deb release/streamd_${{ steps.version.outputs.VERSION }}_amd64.deb cp result-musl/bin/streamd release/streamd-${{ steps.version.outputs.VERSION }}-linux-x86_64 + cp result-windows/bin/streamd.exe release/streamd-${{ steps.version.outputs.VERSION }}-windows-x86_64.exe - name: Create release if: steps.version.outputs.SKIP != 'true' diff --git a/flake.nix b/flake.nix index 38723ae..12cdf69 100644 --- a/flake.nix +++ b/flake.nix @@ -132,6 +132,38 @@ in craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); + mkWindowsCraneLib = + system: + let + pkgs = mkPkgs system; + toolchain = pkgs.rust-bin.stable.latest.default.override { + targets = [ "x86_64-pc-windows-gnu" ]; + }; + in + (crane.mkLib pkgs).overrideToolchain toolchain; + + mkStreamdWindows = + system: + let + pkgs = mkPkgs system; + pkgsCross = pkgs.pkgsCross.mingwW64; + craneLib = mkWindowsCraneLib system; + commonArgs = { + src = craneLib.path ./.; + pname = "streamd"; + inherit version; + strictDeps = true; + CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu"; + CC_x86_64_pc_windows_gnu = "${pkgsCross.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"; + CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${pkgsCross.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"; + nativeBuildInputs = [ pkgsCross.stdenv.cc ]; + buildInputs = [ pkgsCross.windows.pthreads ]; + doCheck = false; + }; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + in + craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); + mkStreamdDeb = system: let @@ -181,9 +213,10 @@ streamd = mkStreamd system; streamd-musl = mkStreamdMusl system; streamd-deb = mkStreamdDeb system; + streamd-windows = mkStreamdWindows system; in { - inherit streamd streamd-musl streamd-deb; + inherit streamd streamd-musl streamd-deb streamd-windows; default = streamd; } ); From c2b4fb5160d4fc80ad0f63dcbbfb3b964a4b8bc8 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Fri, 10 Apr 2026 00:06:13 +0000 Subject: [PATCH 3/6] chore(deps): update rust crate indexmap to v2.14.0 --- Cargo.lock | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bd8f6e1..ccfabbe 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -351,9 +351,9 @@ dependencies = [ [[package]] name = "hashbrown" -version = "0.16.1" +version = "0.17.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "841d1cc9bed7f9236f321df977030373f4a4163ae1a7dbfe1a51a2c1a51d9100" +checksum = "4f467dd6dccf739c208452f8014c75c18bb8301b050ad1cfb27153803edb0f51" [[package]] name = "heck" @@ -393,12 +393,12 @@ checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" [[package]] name = "indexmap" -version = "2.13.1" +version = "2.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "45a8a2b9cb3e0b0c1803dbb0758ffac5de2f425b23c28f518faabd9d805342ff" +checksum = "d466e9454f08e4a911e14806c24e16fba1b4c121d1ea474396f396069cf949d9" dependencies = [ "equivalent", - "hashbrown 0.16.1", + "hashbrown 0.17.0", "serde", "serde_core", ] From 10f4ae282a07f42d7382992ab09cb932e79ac413 Mon Sep 17 00:00:00 2001 From: Renovate Bot Date: Sat, 11 Apr 2026 00:05:42 +0000 Subject: [PATCH 4/6] chore(deps): update rust crate clap_complete to v4.6.1 --- Cargo.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ccfabbe..8f34603 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -197,9 +197,9 @@ dependencies = [ [[package]] name = "clap_complete" -version = "4.6.0" +version = "4.6.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19c9f1dde76b736e3681f28cec9d5a61299cbaae0fce80a68e43724ad56031eb" +checksum = "406e68b4de5c59cfb8f750a7cbd4d31ae153788b8352167c1e5f4fc26e8c91e9" dependencies = [ "clap", ] From 4ded06748ba3e084caa59b8069062a030de95010 Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Tue, 7 Apr 2026 13:49:12 +0200 Subject: [PATCH 5/6] fix: cross-platform compatibility for Windows support - Use directories::BaseDirs for config path fallback instead of hardcoded Unix path - Default to notepad on Windows instead of vi for editor commands - Skip +N line argument for notepad in todo edit (notepad doesn't support it) --- src/cli/commands/edit.rs | 8 +++++++- src/cli/commands/new.rs | 8 +++++++- src/cli/commands/todo.rs | 18 ++++++++++++------ src/config.rs | 4 +++- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/cli/commands/edit.rs b/src/cli/commands/edit.rs index a8761f3..4c15017 100644 --- a/src/cli/commands/edit.rs +++ b/src/cli/commands/edit.rs @@ -67,7 +67,13 @@ pub fn run(number: i32) -> Result<(), StreamdError> { }; if let Some(file_path) = sorted_shards[selected_index].location.get("file") { - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); Command::new(&editor).arg(file_path).status()?; } diff --git a/src/cli/commands/new.rs b/src/cli/commands/new.rs index de7d351..5c3eecb 100644 --- a/src/cli/commands/new.rs +++ b/src/cli/commands/new.rs @@ -24,7 +24,13 @@ pub fn run() -> Result<(), StreamdError> { drop(file); // Open in editor - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); let status = Command::new(&editor).arg(&preliminary_path).status()?; if !status.success() { diff --git a/src/cli/commands/todo.rs b/src/cli/commands/todo.rs index 17bfba2..e54d1e2 100644 --- a/src/cli/commands/todo.rs +++ b/src/cli/commands/todo.rs @@ -92,13 +92,19 @@ pub fn run_edit(number: usize) -> Result<(), StreamdError> { .get("file") .ok_or(StreamdError::MissingFilePath)?; - let editor = std::env::var("EDITOR").unwrap_or_else(|_| "vi".to_string()); - let line_arg = format!("+{}", task.start_line); + let editor = std::env::var("EDITOR").unwrap_or_else(|_| { + if cfg!(windows) { + "notepad".to_string() + } else { + "vi".to_string() + } + }); - let status = Command::new(&editor) - .arg(&line_arg) - .arg(file_path) - .status()?; + let mut cmd = Command::new(&editor); + if !editor.to_lowercase().contains("notepad") { + cmd.arg(format!("+{}", task.start_line)); + } + let status = cmd.arg(file_path).status()?; if !status.success() { return Err(StreamdError::IoError(std::io::Error::other( diff --git a/src/config.rs b/src/config.rs index c828ba9..417e8f0 100644 --- a/src/config.rs +++ b/src/config.rs @@ -37,8 +37,10 @@ impl Settings { fn config_path() -> PathBuf { if let Some(proj_dirs) = ProjectDirs::from("", "", "streamd") { proj_dirs.config_dir().join("config.toml") + } else if let Some(base_dirs) = directories::BaseDirs::new() { + base_dirs.config_dir().join("streamd").join("config.toml") } else { - PathBuf::from("~/.config/streamd/config.toml") + PathBuf::from("streamd_config.toml") } } } From ca2ebd594951567de046732c0b8feda30925335f Mon Sep 17 00:00:00 2001 From: Konstantin Fickel Date: Tue, 7 Apr 2026 13:49:45 +0200 Subject: [PATCH 6/6] feat: add Windows cross-compilation and release artifacts - Add mkWindowsCraneLib using x86_64-pc-windows-gnu target - Add mkStreamdWindows using mingw-w64 toolchain for cross-compilation - Export streamd-windows package from flake - Add Windows build step and .exe artifact to release workflow --- .forgejo/workflows/release.yml | 5 +++++ flake.nix | 35 +++++++++++++++++++++++++++++++++- 2 files changed, 39 insertions(+), 1 deletion(-) diff --git a/.forgejo/workflows/release.yml b/.forgejo/workflows/release.yml index 7c93504..bef91f5 100644 --- a/.forgejo/workflows/release.yml +++ b/.forgejo/workflows/release.yml @@ -49,12 +49,17 @@ jobs: if: steps.version.outputs.SKIP != 'true' run: nix build .#streamd-musl -o result-musl + - name: Build Windows binary + if: steps.version.outputs.SKIP != 'true' + run: nix build .#streamd-windows -o result-windows + - name: Prepare release artifacts if: steps.version.outputs.SKIP != 'true' run: | mkdir -p release cp result-deb release/streamd_${{ steps.version.outputs.VERSION }}_amd64.deb cp result-musl/bin/streamd release/streamd-${{ steps.version.outputs.VERSION }}-linux-x86_64 + cp result-windows/bin/streamd.exe release/streamd-${{ steps.version.outputs.VERSION }}-windows-x86_64.exe - name: Create release if: steps.version.outputs.SKIP != 'true' diff --git a/flake.nix b/flake.nix index 38723ae..12cdf69 100644 --- a/flake.nix +++ b/flake.nix @@ -132,6 +132,38 @@ in craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); + mkWindowsCraneLib = + system: + let + pkgs = mkPkgs system; + toolchain = pkgs.rust-bin.stable.latest.default.override { + targets = [ "x86_64-pc-windows-gnu" ]; + }; + in + (crane.mkLib pkgs).overrideToolchain toolchain; + + mkStreamdWindows = + system: + let + pkgs = mkPkgs system; + pkgsCross = pkgs.pkgsCross.mingwW64; + craneLib = mkWindowsCraneLib system; + commonArgs = { + src = craneLib.path ./.; + pname = "streamd"; + inherit version; + strictDeps = true; + CARGO_BUILD_TARGET = "x86_64-pc-windows-gnu"; + CC_x86_64_pc_windows_gnu = "${pkgsCross.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"; + CARGO_TARGET_X86_64_PC_WINDOWS_GNU_LINKER = "${pkgsCross.stdenv.cc}/bin/x86_64-w64-mingw32-gcc"; + nativeBuildInputs = [ pkgsCross.stdenv.cc ]; + buildInputs = [ pkgsCross.windows.pthreads ]; + doCheck = false; + }; + cargoArtifacts = craneLib.buildDepsOnly commonArgs; + in + craneLib.buildPackage (commonArgs // { inherit cargoArtifacts; }); + mkStreamdDeb = system: let @@ -181,9 +213,10 @@ streamd = mkStreamd system; streamd-musl = mkStreamdMusl system; streamd-deb = mkStreamdDeb system; + streamd-windows = mkStreamdWindows system; in { - inherit streamd streamd-musl streamd-deb; + inherit streamd streamd-musl streamd-deb streamd-windows; default = streamd; } );