mirror of
https://github.com/dwinkler1/np.git
synced 2026-02-19 22:40:57 -05:00
Refactor template: extract scripts, overlays, and hosts into separate modules
Co-authored-by: dwinkler1 <22460147+dwinkler1@users.noreply.github.com>
This commit is contained in:
parent
5e8f07c560
commit
3398a72241
17 changed files with 1185 additions and 422 deletions
65
templates/rde/README.md
Normal file
65
templates/rde/README.md
Normal file
|
|
@ -0,0 +1,65 @@
|
|||
# Research Development Environment (RDE) Template
|
||||
|
||||
This is a Nix flake template for setting up research development environments with support for R, Python, and Julia.
|
||||
|
||||
## Structure
|
||||
|
||||
The template is organized into several directories for better maintainability:
|
||||
|
||||
```
|
||||
templates/rde/
|
||||
├── flake.nix # Main flake configuration (290 lines)
|
||||
├── overlays/ # Nix overlays for packages
|
||||
│ ├── r.nix # R packages configuration
|
||||
│ ├── python.nix # Python packages configuration
|
||||
│ ├── rix.nix # rstats-on-nix integration
|
||||
│ ├── theme.nix # Neovim theme configuration
|
||||
│ └── project-scripts.nix # Project initialization scripts
|
||||
├── hosts/ # Host/command configurations
|
||||
│ ├── default.nix # Merges all host configs
|
||||
│ ├── python.nix # Python commands (marimo, ipy, etc.)
|
||||
│ ├── julia.nix # Julia commands (jl, pluto, etc.)
|
||||
│ ├── r.nix # R commands
|
||||
│ └── utils.nix # Utility commands (initProject, etc.)
|
||||
└── scripts/ # Shell scripts
|
||||
├── initPython.sh # Initialize Python project
|
||||
├── initProject.sh # Initialize project structure
|
||||
├── updateDeps.sh # Update all dependencies
|
||||
└── activateDevenv.sh # Activate devenv shell
|
||||
```
|
||||
|
||||
## Benefits of This Structure
|
||||
|
||||
1. **Modularity**: Each component is in its own file, making it easier to understand and modify
|
||||
2. **Maintainability**: Changes to one language or feature don't affect others
|
||||
3. **Readability**: Main flake.nix is now ~290 lines instead of 688
|
||||
4. **Reusability**: Individual modules can be easily reused or replaced
|
||||
5. **Testability**: Smaller files are easier to test and debug
|
||||
|
||||
## Configuration
|
||||
|
||||
Edit the `config` section in `flake.nix` to customize:
|
||||
|
||||
- `defaultPackageName`: Name of your project/package
|
||||
- `enabledLanguages`: Enable/disable R, Python, Julia support
|
||||
- `enabledPackages`: Enable additional features like devenv
|
||||
- `theme`: Configure Neovim color scheme
|
||||
|
||||
## Extending
|
||||
|
||||
To add new functionality:
|
||||
|
||||
- **New packages**: Add overlays in `overlays/`
|
||||
- **New commands**: Add host configs in `hosts/`
|
||||
- **New scripts**: Add shell scripts in `scripts/`
|
||||
- **New languages**: Create new host and overlay files
|
||||
|
||||
## Usage
|
||||
|
||||
Use this template with:
|
||||
|
||||
```bash
|
||||
nix flake init -t github:dwinkler1/np#rde
|
||||
```
|
||||
|
||||
Then run `direnv allow` or enter the dev shell with `nix develop`.
|
||||
|
|
@ -50,241 +50,24 @@
|
|||
};
|
||||
};
|
||||
};
|
||||
# R packages
|
||||
rOverlay = final: prev: let
|
||||
reqPkgs = with final.rpkgs.rPackages;
|
||||
[
|
||||
broom
|
||||
data_table
|
||||
janitor
|
||||
languageserver
|
||||
reprex
|
||||
styler
|
||||
tidyverse
|
||||
]
|
||||
++ (with final.extraRPackages; [
|
||||
httpgd
|
||||
])
|
||||
++ (prev.lib.optional (builtins.pathExists ./r-packages.nix) (import ./r-packages.nix final.rpkgs));
|
||||
in {
|
||||
quarto = final.rpkgs.quarto.override {extraRPackages = 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 ⬆️ ##
|
||||
###################################
|
||||
|
||||
rixOverlay = final: prev: {rpkgs = inputs.rixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system};};
|
||||
|
||||
extraPkgOverlay = final: prev: let
|
||||
extraTheme = {
|
||||
plugin = prev.vimPlugins."${config.theme.extraColorschemePackage.plugin}";
|
||||
name = config.theme.extraColorschemePackage.name;
|
||||
config = {
|
||||
lua = config.theme.extraColorschemePackage.extraLua;
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit extraTheme;
|
||||
};
|
||||
|
||||
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 "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Existing Python project detected."
|
||||
echo "📦 Ensuring IPython and Marimo are installed..."
|
||||
uv add ipython
|
||||
uv add marimo
|
||||
echo "Run '${config.defaultPackageName}-updateDeps' to update dependencies."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
|
||||
initProjectScript = ''
|
||||
#!/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"
|
||||
)
|
||||
|
||||
for dir in "''${directories[@]}"; do
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
mkdir -p "$dir"
|
||||
echo "✓ Created $dir/"
|
||||
fi
|
||||
done
|
||||
|
||||
# Create essential files
|
||||
if [[ ! -f "README.md" ]]; then
|
||||
cat > README.md << 'EOF'
|
||||
# RDE
|
||||
|
||||
## Project Structure
|
||||
- `data/`: Data files (gitignored)
|
||||
- `docs/`: Documentation
|
||||
- `figures/`: Output figures
|
||||
- `tables/`: Output tables
|
||||
- `src/`: Source code
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Initialize git
|
||||
if [[ ! -d ".git" ]]; then
|
||||
git init
|
||||
echo "✓ Initialized Git repository and added: flake.nix, flake.lock"
|
||||
fi
|
||||
# Check if files are already staged/tracked before adding
|
||||
if ! git diff --cached --name-only | grep -q "flake.nix\|flake.lock" &&
|
||||
! git ls-files --error-unmatch flake.nix flake.lock >/dev/null 2>&1; then
|
||||
echo "✓ Adding flake.nix, flake.lock to Git repository"
|
||||
git add flake.nix flake.lock
|
||||
else
|
||||
echo "✓ flake.nix, flake.lock already tracked/staged in Git"
|
||||
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
|
||||
|
||||
# Devenv
|
||||
.devenv*
|
||||
devenv.local.nix
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "✅ Project setup completed successfully!"
|
||||
'';
|
||||
|
||||
updateDepsScript = ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "🔄 Updating project dependencies..."
|
||||
|
||||
RVER=$( wget -qO- 'https://raw.githubusercontent.com/ropensci/rix/refs/heads/main/inst/extdata/available_df.csv' | tail -n 1 | head -n 1 | cut -d',' -f4 | tr -d '"' ) &&\
|
||||
|
||||
sed -i "s|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\";|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/$RVER\";|" flake.nix
|
||||
echo "✅ R date is $RVER"
|
||||
|
||||
nix flake update
|
||||
echo "✅ Flake inputs updated"
|
||||
|
||||
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
|
||||
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
devenv update
|
||||
echo "✅ Devenv dependencies updated"
|
||||
fi
|
||||
|
||||
echo "🎉 All dependencies updated!"
|
||||
'';
|
||||
|
||||
activateDevenv = ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
echo "🚀 Activating devenv environment..."
|
||||
exec ${config.defaultPackageName}-devenv shell
|
||||
else
|
||||
echo "❌ No devenv.nix file found in the current directory."
|
||||
echo "To create one, run '${config.defaultPackageName}-initDevenv'"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
initPython = prev.writeShellScriptBin "initPython" initPython;
|
||||
initProject = prev.writeShellScriptBin "initProject" initProjectScript;
|
||||
updateDeps = prev.writeShellScriptBin "updateDeps" updateDepsScript;
|
||||
activateDevenv = prev.writeShellScriptBin "activateDevenv" activateDevenv;
|
||||
};
|
||||
# Import overlays from separate files
|
||||
rOverlay = import ./overlays/r.nix;
|
||||
pythonOverlay = import ./overlays/python.nix;
|
||||
rixOverlay = import ./overlays/rix.nix inputs;
|
||||
extraPkgOverlay = import ./overlays/theme.nix config;
|
||||
projectScriptsOverlay = import ./overlays/project-scripts.nix config;
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
|
||||
projectConfig = forSystems (
|
||||
system: let
|
||||
inherit (nixCats) utils;
|
||||
|
|
@ -303,6 +86,7 @@
|
|||
pythonOverlay
|
||||
projectScriptsOverlay
|
||||
];
|
||||
|
||||
categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions (
|
||||
{
|
||||
pkgs,
|
||||
|
|
@ -314,28 +98,14 @@
|
|||
...
|
||||
} @ packageDef: {
|
||||
lspsAndRuntimeDeps = {
|
||||
project = with pkgs; [
|
||||
];
|
||||
julia = with pkgs; [
|
||||
julia-bin
|
||||
];
|
||||
python = with pkgs; [
|
||||
python
|
||||
nodejs
|
||||
basedpyright
|
||||
uv
|
||||
];
|
||||
r = with pkgs; [
|
||||
rWrapper
|
||||
quarto
|
||||
air-formatter
|
||||
];
|
||||
project = with pkgs; [];
|
||||
julia = with pkgs; [julia-bin];
|
||||
python = with pkgs; [python nodejs basedpyright uv];
|
||||
r = with pkgs; [rWrapper quarto air-formatter];
|
||||
};
|
||||
|
||||
startupPlugins = {
|
||||
project = with pkgs.vimPlugins; [
|
||||
pkgs.extraTheme
|
||||
];
|
||||
project = with pkgs.vimPlugins; [pkgs.extraTheme];
|
||||
gitPlugins = with pkgs.neovimPlugins; [
|
||||
{
|
||||
plugin = r;
|
||||
|
|
@ -345,13 +115,13 @@
|
|||
};
|
||||
|
||||
optionalPlugins = {
|
||||
project = with pkgs.vimPlugins; [
|
||||
];
|
||||
project = with pkgs.vimPlugins; [];
|
||||
gitPlugins = with pkgs.neovimPlugins; [
|
||||
cmp-r
|
||||
cmp-pandoc-references
|
||||
];
|
||||
};
|
||||
|
||||
optionalLuaPreInit = {
|
||||
project = [
|
||||
''
|
||||
|
|
@ -370,37 +140,27 @@
|
|||
''
|
||||
];
|
||||
};
|
||||
|
||||
optionalLuaAdditions = {
|
||||
project = [
|
||||
"vim.notify('Project loaded: ${name}')"
|
||||
];
|
||||
project = ["vim.notify('Project loaded: ${name}')"];
|
||||
};
|
||||
|
||||
sharedLibraries = {
|
||||
project = {
|
||||
};
|
||||
project = {};
|
||||
};
|
||||
|
||||
environmentVariables = {
|
||||
project = {
|
||||
};
|
||||
julia = {
|
||||
JULIA_NUM_THREADS = "auto";
|
||||
};
|
||||
project = {};
|
||||
julia = {JULIA_NUM_THREADS = "auto";};
|
||||
python = {
|
||||
# Prevent uv from managing Python downloads
|
||||
UV_PYTHON_DOWNLOADS = "never";
|
||||
# Force uv to use nixpkgs Python interpreter
|
||||
UV_PYTHON = pkgs.python.interpreter;
|
||||
};
|
||||
r = {
|
||||
R_LIBS_USER = "./.Rlibs";
|
||||
};
|
||||
r = {R_LIBS_USER = "./.Rlibs";};
|
||||
};
|
||||
|
||||
extraWrapperArgs = {
|
||||
python = [
|
||||
"--unset PYTHONPATH"
|
||||
];
|
||||
python = ["--unset PYTHONPATH"];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
|
@ -417,166 +177,8 @@
|
|||
settings = {
|
||||
suffix-path = false;
|
||||
suffix-LD = false;
|
||||
# your alias may not conflict with your other packages.
|
||||
aliases = ["pvim"];
|
||||
hosts = {
|
||||
g = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.neovide}/bin/neovide";
|
||||
args = [
|
||||
"--add-flags"
|
||||
"--neovim-bin ${name}"
|
||||
];
|
||||
};
|
||||
};
|
||||
marimo = let
|
||||
marimoInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding Marimo..."
|
||||
uv add marimo
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
uv sync
|
||||
echo "🐍 Launching Marimo..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${marimoInit}"
|
||||
"--add-flags"
|
||||
"run marimo edit \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
py = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.python.interpreter}";
|
||||
};
|
||||
};
|
||||
ipy = let
|
||||
ipythonInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding IPython..."
|
||||
uv add ipython
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
echo "📦 Ensuring IPython is installed..."
|
||||
uv add ipython
|
||||
uv sync
|
||||
echo "🐍 Launching IPython..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${ipythonInit}"
|
||||
"--add-flags"
|
||||
"run ipython \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
jl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=."];
|
||||
};
|
||||
};
|
||||
initJl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e 'using Pkg; Pkg.instantiate(); Pkg.add(\"Pluto\")'"];
|
||||
};
|
||||
};
|
||||
pluto = let
|
||||
runPluto = ''
|
||||
import Pkg; import TOML; Pkg.instantiate();
|
||||
if !isfile("Project.toml") || !haskey(TOML.parsefile(Base.active_project())["deps"], "Pluto")
|
||||
Pkg.add("Pluto");
|
||||
end
|
||||
import Pluto; Pluto.run();
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e '${runPluto}'"];
|
||||
};
|
||||
};
|
||||
r = {
|
||||
enable = config.enabledLanguages.r;
|
||||
path = {
|
||||
value = "${pkgs.rWrapper}/bin/R";
|
||||
args = ["--add-flags" "--no-save --no-restore"];
|
||||
};
|
||||
};
|
||||
initPython = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path.value = "${pkgs.initPython}/bin/initPython";
|
||||
};
|
||||
initProject = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.initProject}/bin/initProject";
|
||||
};
|
||||
};
|
||||
initDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
args = ["--add-flags" "init"];
|
||||
};
|
||||
};
|
||||
activateDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.activateDevenv}/bin/activateDevenv";
|
||||
};
|
||||
};
|
||||
devenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
};
|
||||
};
|
||||
updateDeps = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.updateDeps}/bin/updateDeps";
|
||||
};
|
||||
};
|
||||
node.enable = true;
|
||||
perl.enable = true;
|
||||
ruby.enable = true;
|
||||
};
|
||||
hosts = import ./hosts config pkgs;
|
||||
};
|
||||
categories = {
|
||||
julia = config.enabledLanguages.julia;
|
||||
|
|
|
|||
688
templates/rde/flake.nix.backup
Normal file
688
templates/rde/flake.nix.backup
Normal file
|
|
@ -0,0 +1,688 @@
|
|||
{
|
||||
description = "New Project";
|
||||
|
||||
outputs = {
|
||||
self,
|
||||
nixpkgs,
|
||||
nixCats,
|
||||
...
|
||||
} @ inputs: let
|
||||
#######################
|
||||
### PROJECT CONFIG ####
|
||||
#######################
|
||||
## Set options below:
|
||||
config = rec {
|
||||
## Set project name
|
||||
defaultPackageName = "p";
|
||||
## Enable languages
|
||||
enabledLanguages = {
|
||||
julia = false;
|
||||
python = false;
|
||||
r = true;
|
||||
};
|
||||
## Enable packages
|
||||
enabledPackages = {
|
||||
## Plugins loaded via flake input
|
||||
### Always enable when R is enabled
|
||||
### You can use your own R installation and just enable the plugin
|
||||
gitPlugins = enabledLanguages.r;
|
||||
## Create additional dev shells in the project
|
||||
devenv = false;
|
||||
};
|
||||
theme = rec {
|
||||
## set colortheme and background here
|
||||
### "cyberdream", "onedark", and "tokyonight" are pre-installed
|
||||
colorscheme = "kanagawa";
|
||||
background = "dark";
|
||||
## Add other colortheme packages and config here
|
||||
## The default is a best guess
|
||||
extraColorschemePackage = rec {
|
||||
name = colorscheme;
|
||||
extraLua = ''
|
||||
vim.notify("Loading ${colorscheme} with extra config...")
|
||||
require('${name}').setup({
|
||||
commentStyle = {italic = false},
|
||||
keywordStyle = {italic = false},
|
||||
theme = 'dragon'
|
||||
})
|
||||
'';
|
||||
plugin = name + "-nvim";
|
||||
};
|
||||
};
|
||||
};
|
||||
# R packages
|
||||
rOverlay = final: prev: let
|
||||
reqPkgs = with final.rpkgs.rPackages;
|
||||
[
|
||||
broom
|
||||
data_table
|
||||
janitor
|
||||
languageserver
|
||||
reprex
|
||||
styler
|
||||
tidyverse
|
||||
]
|
||||
++ (with final.extraRPackages; [
|
||||
httpgd
|
||||
])
|
||||
++ (prev.lib.optional (builtins.pathExists ./r-packages.nix) (import ./r-packages.nix final.rpkgs));
|
||||
in {
|
||||
quarto = final.rpkgs.quarto.override {extraRPackages = 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 ⬆️ ##
|
||||
###################################
|
||||
|
||||
rixOverlay = final: prev: {rpkgs = inputs.rixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system};};
|
||||
|
||||
extraPkgOverlay = final: prev: let
|
||||
extraTheme = {
|
||||
plugin = prev.vimPlugins."${config.theme.extraColorschemePackage.plugin}";
|
||||
name = config.theme.extraColorschemePackage.name;
|
||||
config = {
|
||||
lua = config.theme.extraColorschemePackage.extraLua;
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit extraTheme;
|
||||
};
|
||||
|
||||
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 "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Existing Python project detected."
|
||||
echo "📦 Ensuring IPython and Marimo are installed..."
|
||||
uv add ipython
|
||||
uv add marimo
|
||||
echo "Run '${config.defaultPackageName}-updateDeps' to update dependencies."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
|
||||
initProjectScript = ''
|
||||
#!/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"
|
||||
)
|
||||
|
||||
for dir in "''${directories[@]}"; do
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
mkdir -p "$dir"
|
||||
echo "✓ Created $dir/"
|
||||
fi
|
||||
done
|
||||
|
||||
# Create essential files
|
||||
if [[ ! -f "README.md" ]]; then
|
||||
cat > README.md << 'EOF'
|
||||
# RDE
|
||||
|
||||
## Project Structure
|
||||
- `data/`: Data files (gitignored)
|
||||
- `docs/`: Documentation
|
||||
- `figures/`: Output figures
|
||||
- `tables/`: Output tables
|
||||
- `src/`: Source code
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Initialize git
|
||||
if [[ ! -d ".git" ]]; then
|
||||
git init
|
||||
echo "✓ Initialized Git repository and added: flake.nix, flake.lock"
|
||||
fi
|
||||
# Check if files are already staged/tracked before adding
|
||||
if ! git diff --cached --name-only | grep -q "flake.nix\|flake.lock" &&
|
||||
! git ls-files --error-unmatch flake.nix flake.lock >/dev/null 2>&1; then
|
||||
echo "✓ Adding flake.nix, flake.lock to Git repository"
|
||||
git add flake.nix flake.lock
|
||||
else
|
||||
echo "✓ flake.nix, flake.lock already tracked/staged in Git"
|
||||
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
|
||||
|
||||
# Devenv
|
||||
.devenv*
|
||||
devenv.local.nix
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "✅ Project setup completed successfully!"
|
||||
'';
|
||||
|
||||
updateDepsScript = ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "🔄 Updating project dependencies..."
|
||||
|
||||
RVER=$( wget -qO- 'https://raw.githubusercontent.com/ropensci/rix/refs/heads/main/inst/extdata/available_df.csv' | tail -n 1 | head -n 1 | cut -d',' -f4 | tr -d '"' ) &&\
|
||||
|
||||
sed -i "s|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\";|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/$RVER\";|" flake.nix
|
||||
echo "✅ R date is $RVER"
|
||||
|
||||
nix flake update
|
||||
echo "✅ Flake inputs updated"
|
||||
|
||||
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
|
||||
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
devenv update
|
||||
echo "✅ Devenv dependencies updated"
|
||||
fi
|
||||
|
||||
echo "🎉 All dependencies updated!"
|
||||
'';
|
||||
|
||||
activateDevenv = ''
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
echo "🚀 Activating devenv environment..."
|
||||
exec ${config.defaultPackageName}-devenv shell
|
||||
else
|
||||
echo "❌ No devenv.nix file found in the current directory."
|
||||
echo "To create one, run '${config.defaultPackageName}-initDevenv'"
|
||||
exit 1
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
initPython = prev.writeShellScriptBin "initPython" initPython;
|
||||
initProject = prev.writeShellScriptBin "initProject" initProjectScript;
|
||||
updateDeps = prev.writeShellScriptBin "updateDeps" updateDepsScript;
|
||||
activateDevenv = prev.writeShellScriptBin "activateDevenv" activateDevenv;
|
||||
};
|
||||
supportedSystems = [
|
||||
"x86_64-linux"
|
||||
"aarch64-linux"
|
||||
"aarch64-darwin"
|
||||
];
|
||||
forSystems = nixpkgs.lib.genAttrs supportedSystems;
|
||||
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)
|
||||
extraPkgOverlay
|
||||
rixOverlay
|
||||
inputs.fran.overlays.default
|
||||
rOverlay
|
||||
pythonOverlay
|
||||
projectScriptsOverlay
|
||||
];
|
||||
categoryDefinitions = utils.mergeCatDefs prev.categoryDefinitions (
|
||||
{
|
||||
pkgs,
|
||||
settings,
|
||||
categories,
|
||||
name,
|
||||
extra,
|
||||
mkPlugin,
|
||||
...
|
||||
} @ packageDef: {
|
||||
lspsAndRuntimeDeps = {
|
||||
project = with pkgs; [
|
||||
];
|
||||
julia = with pkgs; [
|
||||
julia-bin
|
||||
];
|
||||
python = with pkgs; [
|
||||
python
|
||||
nodejs
|
||||
basedpyright
|
||||
uv
|
||||
];
|
||||
r = with pkgs; [
|
||||
rWrapper
|
||||
quarto
|
||||
air-formatter
|
||||
];
|
||||
};
|
||||
|
||||
startupPlugins = {
|
||||
project = with pkgs.vimPlugins; [
|
||||
pkgs.extraTheme
|
||||
];
|
||||
gitPlugins = with pkgs.neovimPlugins; [
|
||||
{
|
||||
plugin = r;
|
||||
config.lua = "vim.notify('Using project local R plugin')";
|
||||
}
|
||||
];
|
||||
};
|
||||
|
||||
optionalPlugins = {
|
||||
project = with pkgs.vimPlugins; [
|
||||
];
|
||||
gitPlugins = with pkgs.neovimPlugins; [
|
||||
cmp-r
|
||||
cmp-pandoc-references
|
||||
];
|
||||
};
|
||||
optionalLuaPreInit = {
|
||||
project = [
|
||||
''
|
||||
local predicate = function(notif)
|
||||
if not (notif.data.source == "lsp_progress" and notif.data.client_name == "lua_ls") then
|
||||
return true
|
||||
end
|
||||
-- Filter out some LSP progress notifications from 'lua_ls'
|
||||
return notif.msg:find("Diagnosing") == nil and notif.msg:find("semantic tokens") == nil
|
||||
end
|
||||
local custom_sort = function(notif_arr)
|
||||
return MiniNotify.default_sort(vim.tbl_filter(predicate, notif_arr))
|
||||
end
|
||||
require("mini.notify").setup({ content = { sort = custom_sort } })
|
||||
vim.notify = MiniNotify.make_notify()
|
||||
''
|
||||
];
|
||||
};
|
||||
optionalLuaAdditions = {
|
||||
project = [
|
||||
"vim.notify('Project loaded: ${name}')"
|
||||
];
|
||||
};
|
||||
sharedLibraries = {
|
||||
project = {
|
||||
};
|
||||
};
|
||||
|
||||
environmentVariables = {
|
||||
project = {
|
||||
};
|
||||
julia = {
|
||||
JULIA_NUM_THREADS = "auto";
|
||||
};
|
||||
python = {
|
||||
# Prevent uv from managing Python downloads
|
||||
UV_PYTHON_DOWNLOADS = "never";
|
||||
# Force uv to use nixpkgs Python interpreter
|
||||
UV_PYTHON = pkgs.python.interpreter;
|
||||
};
|
||||
r = {
|
||||
R_LIBS_USER = "./.Rlibs";
|
||||
};
|
||||
};
|
||||
|
||||
extraWrapperArgs = {
|
||||
python = [
|
||||
"--unset PYTHONPATH"
|
||||
];
|
||||
};
|
||||
}
|
||||
);
|
||||
|
||||
packageDefinitions =
|
||||
prev.packageDefinitions
|
||||
// {
|
||||
"${config.defaultPackageName}" = utils.mergeCatDefs prev.packageDefinitions.n (
|
||||
{
|
||||
pkgs,
|
||||
name,
|
||||
...
|
||||
}: {
|
||||
settings = {
|
||||
suffix-path = false;
|
||||
suffix-LD = false;
|
||||
# your alias may not conflict with your other packages.
|
||||
aliases = ["pvim"];
|
||||
hosts = {
|
||||
g = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.neovide}/bin/neovide";
|
||||
args = [
|
||||
"--add-flags"
|
||||
"--neovim-bin ${name}"
|
||||
];
|
||||
};
|
||||
};
|
||||
marimo = let
|
||||
marimoInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding Marimo..."
|
||||
uv add marimo
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
uv sync
|
||||
echo "🐍 Launching Marimo..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${marimoInit}"
|
||||
"--add-flags"
|
||||
"run marimo edit \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
py = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.python.interpreter}";
|
||||
};
|
||||
};
|
||||
ipy = let
|
||||
ipythonInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding IPython..."
|
||||
uv add ipython
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
echo "📦 Ensuring IPython is installed..."
|
||||
uv add ipython
|
||||
uv sync
|
||||
echo "🐍 Launching IPython..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${ipythonInit}"
|
||||
"--add-flags"
|
||||
"run ipython \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
jl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=."];
|
||||
};
|
||||
};
|
||||
initJl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e 'using Pkg; Pkg.instantiate(); Pkg.add(\"Pluto\")'"];
|
||||
};
|
||||
};
|
||||
pluto = let
|
||||
runPluto = ''
|
||||
import Pkg; import TOML; Pkg.instantiate();
|
||||
if !isfile("Project.toml") || !haskey(TOML.parsefile(Base.active_project())["deps"], "Pluto")
|
||||
Pkg.add("Pluto");
|
||||
end
|
||||
import Pluto; Pluto.run();
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e '${runPluto}'"];
|
||||
};
|
||||
};
|
||||
r = {
|
||||
enable = config.enabledLanguages.r;
|
||||
path = {
|
||||
value = "${pkgs.rWrapper}/bin/R";
|
||||
args = ["--add-flags" "--no-save --no-restore"];
|
||||
};
|
||||
};
|
||||
initPython = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path.value = "${pkgs.initPython}/bin/initPython";
|
||||
};
|
||||
initProject = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.initProject}/bin/initProject";
|
||||
};
|
||||
};
|
||||
initDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
args = ["--add-flags" "init"];
|
||||
};
|
||||
};
|
||||
activateDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.activateDevenv}/bin/activateDevenv";
|
||||
};
|
||||
};
|
||||
devenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
};
|
||||
};
|
||||
updateDeps = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.updateDeps}/bin/updateDeps";
|
||||
};
|
||||
};
|
||||
node.enable = true;
|
||||
perl.enable = true;
|
||||
ruby.enable = true;
|
||||
};
|
||||
};
|
||||
categories = {
|
||||
julia = config.enabledLanguages.julia;
|
||||
python = config.enabledLanguages.python;
|
||||
r = config.enabledLanguages.r;
|
||||
project = true;
|
||||
gitPlugins = config.enabledPackages.gitPlugins;
|
||||
background = config.theme.background;
|
||||
colorscheme = config.theme.colorscheme;
|
||||
};
|
||||
}
|
||||
);
|
||||
};
|
||||
});
|
||||
in
|
||||
utils.mkAllWithDefault finalPackage
|
||||
);
|
||||
in {
|
||||
packages = projectConfig;
|
||||
devShells = forSystems (system: let
|
||||
pkgs = import nixpkgs {inherit system;};
|
||||
in {
|
||||
default = let
|
||||
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.julia " - ${config.defaultPackageName}-pluto: Launch Pluto.jl notebook")
|
||||
(pkgs.lib.optionalString config.enabledLanguages.julia " - ${config.defaultPackageName}-initJl: Init existing Julia project")
|
||||
(pkgs.lib.optionalString config.enabledLanguages.python " - ${config.defaultPackageName}-marimo: Launch Marimo notebook")
|
||||
(pkgs.lib.optionalString config.enabledLanguages.python " - ${config.defaultPackageName}-py: Run python")
|
||||
(pkgs.lib.optionalString config.enabledLanguages.python " - ${config.defaultPackageName}-ipy: Launch IPython REPL")
|
||||
(pkgs.lib.optionalString config.enabledLanguages.python " - ${config.defaultPackageName}-initPython: Init python project")
|
||||
(pkgs.lib.optionalString config.enabledPackages.devenv " - ${config.defaultPackageName}-initDevenv: Init devenv project")
|
||||
(pkgs.lib.optionalString config.enabledPackages.devenv " - ${config.defaultPackageName}-devenv: Run devenv")
|
||||
" "
|
||||
"To adjust options run: ${config.defaultPackageName} flake.nix"
|
||||
]);
|
||||
in
|
||||
pkgs.mkShell {
|
||||
name = config.defaultPackageName;
|
||||
packages = [projectConfig.${system}.default];
|
||||
inputsFrom = [];
|
||||
shellHook = ''
|
||||
echo ""
|
||||
echo "=========================================================================="
|
||||
echo "🎯 ${config.defaultPackageName} Development Environment"
|
||||
echo "---"
|
||||
echo "📝 Run '${config.defaultPackageName}-initProject' 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 ""
|
||||
${pkgs.lib.optionalString config.enabledPackages.devenv "${config.defaultPackageName}-activateDevenv"}
|
||||
echo ""
|
||||
'';
|
||||
};
|
||||
});
|
||||
};
|
||||
inputs = {
|
||||
rixpkgs.url = "github:rstats-on-nix/nixpkgs/2025-12-15";
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-25.11";
|
||||
nixCats = {
|
||||
url = "github:dwinkler1/nixCatsConfig";
|
||||
inputs = {
|
||||
nixpkgs.follows = "nixpkgs";
|
||||
rixpkgs.follows = "rixpkgs";
|
||||
fran.follows = "fran";
|
||||
plugins-cmp-pandoc-references.follows = "plugins-cmp-pandoc-references";
|
||||
plugins-cmp-r.follows = "plugins-cmp-r";
|
||||
plugins-r.follows = "plugins-r";
|
||||
};
|
||||
};
|
||||
## Extra R packages
|
||||
fran = {
|
||||
url = "github:dwinkler1/fran";
|
||||
inputs = {
|
||||
nixpkgs.follows = "rixpkgs";
|
||||
nvimcom.follows = "plugins-r";
|
||||
};
|
||||
};
|
||||
## Git Plugins
|
||||
"plugins-r" = {
|
||||
url = "github:R-nvim/R.nvim/v0.99.1";
|
||||
flake = false;
|
||||
};
|
||||
"plugins-cmp-r" = {
|
||||
url = "github:R-nvim/cmp-r";
|
||||
flake = false;
|
||||
};
|
||||
"plugins-cmp-pandoc-references" = {
|
||||
url = "github:jmbuhr/cmp-pandoc-references";
|
||||
flake = false;
|
||||
};
|
||||
};
|
||||
nixConfig = {
|
||||
extra-substituters = [
|
||||
"https://rstats-on-nix.cachix.org"
|
||||
"https://rde.cachix.org"
|
||||
];
|
||||
extra-trusted-public-keys = [
|
||||
"rstats-on-nix.cachix.org-1:vdiiVgocg6WeJrODIqdprZRUrhi1JzhBnXv7aWI6+F0="
|
||||
"rde.cachix.org-1:yRxQYM+69N/dVER6HNWRjsjytZnJVXLS/+t/LI9d1D4="
|
||||
];
|
||||
};
|
||||
}
|
||||
8
templates/rde/hosts/default.nix
Normal file
8
templates/rde/hosts/default.nix
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
# Merges all host configurations from separate modules
|
||||
config: pkgs: let
|
||||
pythonHosts = import ./python.nix config pkgs;
|
||||
juliaHosts = import ./julia.nix config pkgs;
|
||||
rHosts = import ./r.nix config pkgs;
|
||||
utilsHosts = import ./utils.nix config pkgs;
|
||||
in
|
||||
pythonHosts // juliaHosts // rHosts // utilsHosts
|
||||
34
templates/rde/hosts/julia.nix
Normal file
34
templates/rde/hosts/julia.nix
Normal file
|
|
@ -0,0 +1,34 @@
|
|||
# Julia-related host configurations
|
||||
config: pkgs: {
|
||||
jl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=."];
|
||||
};
|
||||
};
|
||||
|
||||
initJl = {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e 'using Pkg; Pkg.instantiate(); Pkg.add(\"Pluto\")'"];
|
||||
};
|
||||
};
|
||||
|
||||
pluto = let
|
||||
runPluto = ''
|
||||
import Pkg; import TOML; Pkg.instantiate();
|
||||
if !isfile("Project.toml") || !haskey(TOML.parsefile(Base.active_project())["deps"], "Pluto")
|
||||
Pkg.add("Pluto");
|
||||
end
|
||||
import Pluto; Pluto.run();
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.julia;
|
||||
path = {
|
||||
value = "${pkgs.julia-bin}/bin/julia";
|
||||
args = ["--add-flags" "--project=. -e '${runPluto}'"];
|
||||
};
|
||||
};
|
||||
}
|
||||
82
templates/rde/hosts/python.nix
Normal file
82
templates/rde/hosts/python.nix
Normal file
|
|
@ -0,0 +1,82 @@
|
|||
# Python-related host configurations
|
||||
config: pkgs: {
|
||||
marimo = let
|
||||
marimoInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding Marimo..."
|
||||
uv add marimo
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
uv sync
|
||||
echo "🐍 Launching Marimo..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${marimoInit}"
|
||||
"--add-flags"
|
||||
"run marimo edit \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
py = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.python.interpreter}";
|
||||
};
|
||||
};
|
||||
|
||||
ipy = let
|
||||
ipythonInit = ''
|
||||
set -euo pipefail
|
||||
if [[ ! -f "pyproject.toml" ]]; then
|
||||
echo "🐍 Initializing UV project..."
|
||||
uv init
|
||||
echo "📦 Adding IPython..."
|
||||
uv add ipython
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "✅ Python project initialized!"
|
||||
echo "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Syncing existing project..."
|
||||
echo "📦 Ensuring IPython is installed..."
|
||||
uv add ipython
|
||||
uv sync
|
||||
echo "🐍 Launching IPython..."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
'';
|
||||
in {
|
||||
enable = config.enabledLanguages.python;
|
||||
path = {
|
||||
value = "${pkgs.uv}/bin/uv";
|
||||
args = [
|
||||
"--run"
|
||||
"${ipythonInit}"
|
||||
"--add-flags"
|
||||
"run ipython \"$@\""
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
initPython = {
|
||||
enable = config.enabledLanguages.python;
|
||||
path.value = "${pkgs.initPython}/bin/initPython";
|
||||
};
|
||||
}
|
||||
10
templates/rde/hosts/r.nix
Normal file
10
templates/rde/hosts/r.nix
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
# R-related host configurations
|
||||
config: pkgs: {
|
||||
r = {
|
||||
enable = config.enabledLanguages.r;
|
||||
path = {
|
||||
value = "${pkgs.rWrapper}/bin/R";
|
||||
args = ["--add-flags" "--no-save --no-restore"];
|
||||
};
|
||||
};
|
||||
}
|
||||
53
templates/rde/hosts/utils.nix
Normal file
53
templates/rde/hosts/utils.nix
Normal file
|
|
@ -0,0 +1,53 @@
|
|||
# Utility and common host configurations
|
||||
config: pkgs: {
|
||||
g = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.neovide}/bin/neovide";
|
||||
args = [
|
||||
"--add-flags"
|
||||
"--neovim-bin ${config.defaultPackageName}"
|
||||
];
|
||||
};
|
||||
};
|
||||
|
||||
initProject = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.initProject}/bin/initProject";
|
||||
};
|
||||
};
|
||||
|
||||
initDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
args = ["--add-flags" "init"];
|
||||
};
|
||||
};
|
||||
|
||||
activateDevenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.activateDevenv}/bin/activateDevenv";
|
||||
};
|
||||
};
|
||||
|
||||
devenv = {
|
||||
enable = config.enabledPackages.devenv;
|
||||
path = {
|
||||
value = "${pkgs.devenv}/bin/devenv";
|
||||
};
|
||||
};
|
||||
|
||||
updateDeps = {
|
||||
enable = true;
|
||||
path = {
|
||||
value = "${pkgs.updateDeps}/bin/updateDeps";
|
||||
};
|
||||
};
|
||||
|
||||
node.enable = true;
|
||||
perl.enable = true;
|
||||
ruby.enable = true;
|
||||
}
|
||||
14
templates/rde/overlays/project-scripts.nix
Normal file
14
templates/rde/overlays/project-scripts.nix
Normal file
|
|
@ -0,0 +1,14 @@
|
|||
# Project scripts overlay
|
||||
config: final: prev: let
|
||||
# Helper function to substitute config placeholders in scripts
|
||||
substituteScript = scriptPath:
|
||||
prev.lib.replaceStrings
|
||||
["@defaultPackageName@"]
|
||||
[config.defaultPackageName]
|
||||
(builtins.readFile scriptPath);
|
||||
in {
|
||||
initPython = prev.writeShellScriptBin "initPython" (substituteScript ./scripts/initPython.sh);
|
||||
initProject = prev.writeShellScriptBin "initProject" (substituteScript ./scripts/initProject.sh);
|
||||
updateDeps = prev.writeShellScriptBin "updateDeps" (substituteScript ./scripts/updateDeps.sh);
|
||||
activateDevenv = prev.writeShellScriptBin "activateDevenv" (substituteScript ./scripts/activateDevenv.sh);
|
||||
}
|
||||
7
templates/rde/overlays/python.nix
Normal file
7
templates/rde/overlays/python.nix
Normal file
|
|
@ -0,0 +1,7 @@
|
|||
# Python packages overlay
|
||||
final: prev: {
|
||||
python = prev.python3.withPackages (pyPackages:
|
||||
with pyPackages; [
|
||||
requests
|
||||
]);
|
||||
}
|
||||
20
templates/rde/overlays/r.nix
Normal file
20
templates/rde/overlays/r.nix
Normal file
|
|
@ -0,0 +1,20 @@
|
|||
# R packages overlay
|
||||
final: prev: let
|
||||
reqPkgs = with final.rpkgs.rPackages;
|
||||
[
|
||||
broom
|
||||
data_table
|
||||
janitor
|
||||
languageserver
|
||||
reprex
|
||||
styler
|
||||
tidyverse
|
||||
]
|
||||
++ (with final.extraRPackages; [
|
||||
httpgd
|
||||
])
|
||||
++ (prev.lib.optional (builtins.pathExists ./r-packages.nix) (import ./r-packages.nix final.rpkgs));
|
||||
in {
|
||||
quarto = final.rpkgs.quarto.override {extraRPackages = reqPkgs;};
|
||||
rWrapper = final.rpkgs.rWrapper.override {packages = reqPkgs;};
|
||||
}
|
||||
4
templates/rde/overlays/rix.nix
Normal file
4
templates/rde/overlays/rix.nix
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
# Rix overlay for R packages from rstats-on-nix
|
||||
inputs: final: prev: {
|
||||
rpkgs = inputs.rixpkgs.legacyPackages.${prev.stdenv.hostPlatform.system};
|
||||
}
|
||||
12
templates/rde/overlays/theme.nix
Normal file
12
templates/rde/overlays/theme.nix
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
# Extra theme packages overlay
|
||||
config: final: prev: let
|
||||
extraTheme = {
|
||||
plugin = prev.vimPlugins."${config.theme.extraColorschemePackage.plugin}";
|
||||
name = config.theme.extraColorschemePackage.name;
|
||||
config = {
|
||||
lua = config.theme.extraColorschemePackage.extraLua;
|
||||
};
|
||||
};
|
||||
in {
|
||||
inherit extraTheme;
|
||||
}
|
||||
10
templates/rde/scripts/activateDevenv.sh
Normal file
10
templates/rde/scripts/activateDevenv.sh
Normal file
|
|
@ -0,0 +1,10 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
echo "🚀 Activating devenv environment..."
|
||||
exec @defaultPackageName@-devenv shell
|
||||
else
|
||||
echo "❌ No devenv.nix file found in the current directory."
|
||||
echo "To create one, run '@defaultPackageName@-initDevenv'"
|
||||
exit 1
|
||||
fi
|
||||
104
templates/rde/scripts/initProject.sh
Normal file
104
templates/rde/scripts/initProject.sh
Normal file
|
|
@ -0,0 +1,104 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
PROJECT_NAME="${1:-@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"
|
||||
)
|
||||
|
||||
for dir in "${directories[@]}"; do
|
||||
if [[ ! -d "$dir" ]]; then
|
||||
mkdir -p "$dir"
|
||||
echo "✓ Created $dir/"
|
||||
fi
|
||||
done
|
||||
|
||||
# Create essential files
|
||||
if [[ ! -f "README.md" ]]; then
|
||||
cat > README.md << 'EOF'
|
||||
# RDE
|
||||
|
||||
## Project Structure
|
||||
- `data/`: Data files (gitignored)
|
||||
- `docs/`: Documentation
|
||||
- `figures/`: Output figures
|
||||
- `tables/`: Output tables
|
||||
- `src/`: Source code
|
||||
|
||||
EOF
|
||||
fi
|
||||
|
||||
# Initialize git
|
||||
if [[ ! -d ".git" ]]; then
|
||||
git init
|
||||
echo "✓ Initialized Git repository and added: flake.nix, flake.lock"
|
||||
fi
|
||||
# Check if files are already staged/tracked before adding
|
||||
if ! git diff --cached --name-only | grep -q "flake.nix\|flake.lock" &&
|
||||
! git ls-files --error-unmatch flake.nix flake.lock >/dev/null 2>&1; then
|
||||
echo "✓ Adding flake.nix, flake.lock to Git repository"
|
||||
git add flake.nix flake.lock
|
||||
else
|
||||
echo "✓ flake.nix, flake.lock already tracked/staged in Git"
|
||||
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
|
||||
|
||||
# Devenv
|
||||
.devenv*
|
||||
devenv.local.nix
|
||||
|
||||
# direnv
|
||||
.direnv
|
||||
|
||||
# pre-commit
|
||||
.pre-commit-config.yaml
|
||||
EOF
|
||||
fi
|
||||
|
||||
echo "✅ Project setup completed successfully!"
|
||||
21
templates/rde/scripts/initPython.sh
Normal file
21
templates/rde/scripts/initPython.sh
Normal file
|
|
@ -0,0 +1,21 @@
|
|||
#!/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 "run 'uv add PACKAGE' to add more python packages."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
else
|
||||
echo "--------------------------------------------------------------------------"
|
||||
echo "🔄 Existing Python project detected."
|
||||
echo "📦 Ensuring IPython and Marimo are installed..."
|
||||
uv add ipython
|
||||
uv add marimo
|
||||
echo "Run '@defaultPackageName@-updateDeps' to update dependencies."
|
||||
echo "--------------------------------------------------------------------------"
|
||||
fi
|
||||
29
templates/rde/scripts/updateDeps.sh
Normal file
29
templates/rde/scripts/updateDeps.sh
Normal file
|
|
@ -0,0 +1,29 @@
|
|||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
|
||||
echo "🔄 Updating project dependencies..."
|
||||
|
||||
RVER=$( wget -qO- 'https://raw.githubusercontent.com/ropensci/rix/refs/heads/main/inst/extdata/available_df.csv' | tail -n 1 | head -n 1 | cut -d',' -f4 | tr -d '"' ) &&\
|
||||
|
||||
sed -i "s|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/[0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\";|rixpkgs.url = \"github:rstats-on-nix/nixpkgs/$RVER\";|" flake.nix
|
||||
echo "✅ R date is $RVER"
|
||||
|
||||
nix flake update
|
||||
echo "✅ Flake inputs updated"
|
||||
|
||||
if [[ -f "pyproject.toml" ]]; then
|
||||
uv sync --upgrade
|
||||
echo "✅ Python dependencies updated"
|
||||
fi
|
||||
|
||||
if [[ -f "Project.toml" ]]; then
|
||||
@defaultPackageName@-jl -e "using Pkg; Pkg.update()"
|
||||
echo "✅ Julia dependencies updated"
|
||||
fi
|
||||
|
||||
if [[ -f "devenv.nix" ]]; then
|
||||
devenv update
|
||||
echo "✅ Devenv dependencies updated"
|
||||
fi
|
||||
|
||||
echo "🎉 All dependencies updated!"
|
||||
Loading…
Add table
Add a link
Reference in a new issue