Working template

This commit is contained in:
Daniel Winkler 2025-08-28 21:19:49 +10:00
commit 144eebbcfa
2 changed files with 277 additions and 132 deletions

29
templates/n/flake.lock generated
View file

@ -6,7 +6,6 @@
"nixpkgs": [ "nixpkgs": [
"nixpkgs" "nixpkgs"
], ],
"nixpkgs-unstable": "nixpkgs-unstable",
"plugins-cmp-pandoc-references": "plugins-cmp-pandoc-references", "plugins-cmp-pandoc-references": "plugins-cmp-pandoc-references",
"plugins-cmp-r": "plugins-cmp-r", "plugins-cmp-r": "plugins-cmp-r",
"plugins-r": "plugins-r", "plugins-r": "plugins-r",
@ -15,11 +14,11 @@
] ]
}, },
"locked": { "locked": {
"lastModified": 1756305715, "lastModified": 1756379633,
"narHash": "sha256-GuNro+bHHMde1X2uoaDS0UwJa1aaVTDvG4KmQOmCAWE=", "narHash": "sha256-REv+GIfWkyCIHfcPzotqpaSHha0LPZ300KsJL+9kP40=",
"owner": "dwinkler1", "owner": "dwinkler1",
"repo": "nixCatsConfig", "repo": "nixCatsConfig",
"rev": "e0f5193d7299c36724d17728511260e0d453f0dc", "rev": "e39a1272ef82cd467fb0c29d0b8a0ccdca672f67",
"type": "github" "type": "github"
}, },
"original": { "original": {
@ -45,27 +44,11 @@
}, },
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1756159630, "lastModified": 1756288264,
"narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=", "narHash": "sha256-Om8adB1lfkU7D33VpR+/haZ2gI5r3Q+ZbIPzE5sYnwE=",
"owner": "nixos", "owner": "nixos",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b", "rev": "ddd1826f294a0ee5fdc198ab72c8306a0ea73aa9",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1756159630,
"narHash": "sha256-ohMvsjtSVdT/bruXf5ClBh8ZYXRmD4krmjKrXhEvwMg=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "84c256e42600cb0fdf25763b48d28df2f25a0c8b",
"type": "github" "type": "github"
}, },
"original": { "original": {

View file

@ -3,10 +3,12 @@
inputs = { inputs = {
rixpkgs.url = "https://github.com/rstats-on-nix/nixpkgs/archive/2025-08-11.tar.gz"; rixpkgs.url = "https://github.com/rstats-on-nix/nixpkgs/archive/2025-08-11.tar.gz";
nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable"; nixpkgs.url = "github:nixos/nixpkgs/nixpkgs-unstable";
nixCats.url = "github:dwinkler1/nixCatsConfig"; nixCats = {
nixCats.inputs.nixpkgs.follows = "nixpkgs"; url = "github:dwinkler1/nixCatsConfig";
nixCats.inputs.rixpkgs.follows = "rixpkgs"; inputs.nixpkgs.follows = "nixpkgs";
## All git packages managed per project inputs.rixpkgs.follows = "rixpkgs";
};
## Git Plugins
"plugins-r" = { "plugins-r" = {
url = "github:R-nvim/R.nvim"; url = "github:R-nvim/R.nvim";
flake = false; flake = false;
@ -26,38 +28,35 @@
nixCats, nixCats,
... ...
} @ inputs: let } @ inputs: let
forSystems = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all; #######################
### PROJECT CONFIG ####
#######################
## Set options below:
config = rec {
## Set project name
defaultPackageName = "p"; defaultPackageName = "p";
projectConfig = forSystems ( ## Enable languages
system: let enabledLanguages = {
inherit (nixCats) utils; julia = false;
inherit defaultPackageName; python = false;
prevPackage = nixCats.packages.${system}.default; r = false;
finalPackage = prevPackage.override (prev: { };
name = defaultPackageName; ## Enable packages
dependencyOverlays = enabledPackages = {
prev.dependencyOverlays ## Plugins loaded via flake input
++ [ ### Always enable when R is enabled
(utils.standardPluginOverlay inputs) ### You can use your own R installation and just enable the plugin
## Pull in local rix copy gitPlugins = enabledLanguages.r;
(final: prev: { };
rpkgs = inputs.rixpkgs.legacyPackages.${prev.system}; };
}) # R packages
## Define project level R packages rixOverlay = final: prev: {rpkgs = inputs.rixpkgs.legacyPackages.${prev.system};};
( rOverlay = final: prev: let
final: prev: let reqPkgs = with final.rpkgs.rPackages; [
reqPkgs = with prev.rpkgs.rPackages; [
Hmisc
Rcpp
arm
broom broom
car
data_table data_table
devtools
janitor janitor
konfound
languageserver languageserver
quarto
reprex reprex
styler styler
tidyverse tidyverse
@ -74,25 +73,176 @@
}) })
]; ];
in { in {
quarto = prev.rpkgs.quarto.override {extraRPackages = reqPkgs;}; quarto = final.rpkgs.quarto.override {extraRPackages = reqPkgs;};
rWrapper = prev.rpkgs.rWrapper.override {packages = reqPkgs;}; rWrapper = final.rpkgs.rWrapper.override {packages = reqPkgs;};
} };
# Python packages
pythonOverlay = final: prev: {
python = prev.python3.withPackages (pyPackages:
with pyPackages; [
requests
]);
};
###################################
## ⬆️ BASIC CONFIG ABOVE HERE ⬆️ ##
###################################
projectScriptsOverlay = final: prev: let
initPython = ''
#!/usr/bin/env bash
set -euo pipefail
if [[ ! -f "pyproject.toml" ]]; then
echo "🐍 Initializing UV project..."
uv init
echo "📦 Adding ipython and marimo..."
uv add ipython
uv add marimo
echo "--------------------------------------------------------------------------"
echo " Python project initialized!"
echo "--------------------------------------------------------------------------"
else
echo "--------------------------------------------------------------------------"
echo "🔄 Existing Python project detected."
echo "Run '${config.defaultPackageName}-updateDeps' to update dependencies."
echo "--------------------------------------------------------------------------"
fi
'';
mkDirsScript = ''
#!/usr/bin/env bash
set -euo pipefail
PROJECT_NAME="''${1:-${config.defaultPackageName}}"
echo "🚀 Setting up project: $PROJECT_NAME"
# Create directory structure
directories=(
"data/raw"
"data/processed"
"data/interim"
"docs"
"figures"
"tables"
"src/analysis"
"src/data_prep"
"src/explore"
"src/utils"
) )
## Define project level Python Packages for dir in "''${directories[@]}"; do
## Only use if uv should not be used mkdir -p "$dir"
( echo " Created $dir/"
final: prev: let done
reqPkgs = pyPackages:
with pyPackages; [ # Create essential files
numpy if [[ ! -f "README.md" ]]; then
polars cat > README.md << 'EOF'
requests # $PROJECT_NAME
];
## Project Structure
- `data/`: Data files (gitignored)
- `docs/`: Documentation
- `figures/`: Output figures
- `tables/`: Output tables
- `src/`: Source code
## Usage
- Julia environment: `$PROJECT_NAME-jl`
- Python environment: `$PROJECT_NAME-m` (Marimo)
- R environment: `$PROJECT_NAME-r`
- Neovide: `$PROJECT_NAME-g`
- Neovim: `$PROJECT_NAME`
- Update: `$PROJECT_NAME-updateDeps`
EOF
fi
# Create .gitignore
if [[ ! -f ".gitignore" ]]; then
cat > .gitignore << 'EOF'
# Data files
data/
*.csv
*.docx
*.xlsx
*.parquet
# R specific
.Rproj.user/
.Rhistory
.RData
.Ruserdata
*.Rproj
.Rlibs/
# Python specific
__pycache__/
*.pyc
.pytest_cache/
.venv/
# Jupyter
.ipynb_checkpoints/
# IDE
.vscode/
.idea/
# OS
.DS_Store
Thumbs.db
EOF
fi
echo " Project setup completed successfully!"
'';
updateDepsScript = ''
#!/usr/bin/env bash
set -euo pipefail
echo "🔄 Updating project dependencies..."
if [[ -f "flake.lock" ]]; then
nix flake update
echo " Flake inputs updated"
fi
if [[ -f "pyproject.toml" ]]; then
uv sync --upgrade
echo " Python dependencies updated"
fi
if [[ -f "Project.toml" ]]; then
${config.defaultPackageName}-jl -e "using Pkg; Pkg.update()"
echo " Julia dependencies updated"
fi
echo "🎉 All dependencies updated!"
'';
in { in {
python = prev.python3.withPackages reqPkgs; initPython = prev.writeShellScriptBin "initPython" initPython;
} mkDirs = prev.writeShellScriptBin "mkDirs" mkDirsScript;
) updateDeps = prev.writeShellScriptBin "updateDeps" updateDepsScript;
};
forSystems = nixpkgs.lib.genAttrs nixpkgs.lib.platforms.all;
projectConfig = forSystems (
system: let
inherit (nixCats) utils;
inherit (config) defaultPackageName;
prevPackage = nixCats.packages.${system}.default;
finalPackage = prevPackage.override (prev: {
name = config.defaultPackageName;
dependencyOverlays =
prev.dependencyOverlays
++ [
(utils.standardPluginOverlay inputs)
rixOverlay
rOverlay
pythonOverlay
projectScriptsOverlay
]; ];
categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions ( categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions (
{ {
@ -198,7 +348,7 @@
packageDefinitions = packageDefinitions =
prev.packageDefinitions prev.packageDefinitions
// { // {
"${defaultPackageName}" = utils.mergeCatDefs prev.packageDefinitions.n ( p = utils.mergeCatDefs prev.packageDefinitions.n (
{ {
pkgs, pkgs,
name, name,
@ -221,74 +371,64 @@
}; };
}; };
m = let m = let
preHookInit = '' marimoInit = ''
# Check if pyproject.toml exists set -euo pipefail
if [ ! -f "pyproject.toml" ]; then echo "🔄 Syncing existing project..."
echo "pyproject.toml not found. Initializing new UV project..."
# Initialize UV project
uv init
# Check if uv init was successful
if [ $? -eq 0 ]; then
echo "UV project initialized successfully."
# Add marimo dependency
echo "Adding marimo dependency..."
uv add marimo
if [ $? -eq 0 ]; then
echo "Marimo added successfully!"
else
echo "Error: Failed to add marimo dependency."
exit 1
fi
else
echo "Error: Failed to initialize UV project."
exit 1
fi
else
echo "pyproject.toml already exists. Syncing...."
uv sync uv sync
fi
''; '';
in { in {
enable = true; enable = config.enabledLanguages.python;
path = { path = {
value = "${pkgs.uv}/bin/uv"; value = "${pkgs.uv}/bin/uv";
args = [ args = [
"--run" "--run"
"${preHookInit}" "${marimoInit}"
"--add-flags" "--add-flags"
"run marimo edit" "run marimo edit \"$@\""
]; ];
}; };
}; };
jl = { jl = {
enable = false; enable = config.enabledLanguages.julia;
path = { path = {
value = "${pkgs.julia-bin}/bin/julia"; value = "${pkgs.julia-bin}/bin/julia";
args = ["--add-flags" "--project=@."]; args = ["--add-flags" "--project=."];
}; };
}; };
r = { r = {
enable = true; enable = config.enabledLanguages.r;
path = { path = {
value = "${pkgs.rWrapper}/bin/R"; value = "${pkgs.rWrapper}/bin/R";
args = ["--add-flags" "--no-save --no-restore"]; args = ["--add-flags" "--no-save --no-restore"];
}; };
}; };
initPython = {
enable = config.enabledLanguages.python;
path.value = "${pkgs.initPython}/bin/initPython";
};
mkDirs = {
enable = true;
path = {
value = "${pkgs.mkDirs}/bin/mkDirs";
};
};
updateDeps = {
enable = true;
path = {
value = "${pkgs.updateDeps}/bin/updateDeps";
};
};
node.enable = true; node.enable = true;
perl.enable = true; perl.enable = true;
ruby.enable = true; ruby.enable = true;
}; };
}; };
categories = { categories = {
julia = false; julia = config.enabledLanguages.julia;
python = false; python = config.enabledLanguages.python;
r = true; r = config.enabledLanguages.r;
project = true; project = true;
gitPlugins = true; gitPlugins = config.enabledPackages.gitPlugins;
}; };
} }
); );
@ -302,11 +442,33 @@
devShells = forSystems (system: let devShells = forSystems (system: let
pkgs = import nixpkgs {inherit system;}; pkgs = import nixpkgs {inherit system;};
in { in {
default = pkgs.mkShell { default = let
name = defaultPackageName; shellCmds = pkgs.lib.concatLines (pkgs.lib.filter (cmd: cmd != "") [
(pkgs.lib.optionalString config.enabledLanguages.r " - ${config.defaultPackageName}-r: Launch R console")
(pkgs.lib.optionalString config.enabledLanguages.julia " - ${config.defaultPackageName}-jl: Launch Julia REPL")
(pkgs.lib.optionalString config.enabledLanguages.python " - ${config.defaultPackageName}-m: Launch Marimo notebook")
"See options in flake.nix"
]);
in
pkgs.mkShell {
name = config.defaultPackageName;
packages = [projectConfig.${system}.default]; packages = [projectConfig.${system}.default];
inputsFrom = []; inputsFrom = [];
shellHook = '' shellHook = ''
echo ""
${pkgs.lib.optionalString config.enabledLanguages.python "${config.defaultPackageName}-initPython"}
echo "=========================================================================="
echo "🎯 ${config.defaultPackageName} Development Environment"
echo "---"
echo "📝 Run '${config.defaultPackageName}-mkDirs' to set up project structure"
echo "🔄 Run '${config.defaultPackageName}-updateDeps' to update all dependencies"
echo "---"
echo "🚀 Available commands:"
echo " - ${config.defaultPackageName}: Launch Neovim"
echo " - ${config.defaultPackageName}-g: Launch Neovide"
echo "${shellCmds}"
echo "=========================================================================="
echo ""
''; '';
}; };
}); });