Compare commits
1 commit
Author | SHA1 | Date | |
---|---|---|---|
52d89f41eb |
909 changed files with 29034 additions and 69989 deletions
.gitattributes.gitignoreREADME.md_outputs.nix
apps
README.mdbuildApp.nix
config
default.nixextract-subs
gen-docs
list2series
mc-mods
packages.nixpin-inputs
update-sources
common
default.nix
home
5
.gitattributes
vendored
5
.gitattributes
vendored
|
@ -1,5 +0,0 @@
|
||||||
flake.lock -diff
|
|
||||||
flake.nix -diff
|
|
||||||
**/non-declarative-conf -diff
|
|
||||||
**/package-lock.json -diff
|
|
||||||
**/HomeAssistantGenerated -diff
|
|
28
.gitignore
vendored
28
.gitignore
vendored
|
@ -1,23 +1,9 @@
|
||||||
# Python
|
|
||||||
*.egg-info
|
*.egg-info
|
||||||
|
|
||||||
# NPM
|
|
||||||
*node_modules
|
|
||||||
*build/
|
|
||||||
|
|
||||||
# Direnv
|
|
||||||
*.direnv/
|
|
||||||
|
|
||||||
# Generated by nix
|
|
||||||
result*
|
|
||||||
!results/
|
|
||||||
.nixd.json
|
|
||||||
|
|
||||||
## AGS
|
|
||||||
**/vars.ts
|
|
||||||
**/config.js
|
|
||||||
*icons
|
|
||||||
**/types
|
|
||||||
|
|
||||||
# Other
|
|
||||||
*.temp
|
*.temp
|
||||||
|
*node_modules/
|
||||||
|
*types
|
||||||
|
*build/
|
||||||
|
result*
|
||||||
|
*config.js
|
||||||
|
*icons
|
||||||
|
*.direnv/
|
||||||
|
|
80
README.md
80
README.md
|
@ -1,6 +1,6 @@
|
||||||
# My NixOS configs
|
# My NixOS configs
|
||||||
|
|
||||||
## AGS
|
## Ags
|
||||||
|
|
||||||
You might find it weird that most of my config is written in TypeScript.
|
You might find it weird that most of my config is written in TypeScript.
|
||||||
That's because all my desktops run
|
That's because all my desktops run
|
||||||
|
@ -16,21 +16,11 @@ in TypeScript because it's the scripting language I am most comfortable with.
|
||||||
|
|
||||||
### General
|
### General
|
||||||
|
|
||||||
This repo is the complete configuration of machines I own running NixOS or Nix
|
This repo is the complete configuration of machines I own,
|
||||||
and any other related smaller projects exposed by a Nix Flake.
|
running NixOS or Nix. I tend to mix Home-Manager and NixOS
|
||||||
|
a lot to make my custom modules by using my global vars system
|
||||||
Its main directory structure is based on a flake's
|
explained
|
||||||
[outputs](https://wiki.nixos.org/wiki/Flakes#Output_schema).
|
[here](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/devices)
|
||||||
|
|
||||||
I try to follow a few rules to better organise my Nix code:
|
|
||||||
|
|
||||||
- Every main subdirectory only has an optional `default.nix` and subfolders for each
|
|
||||||
of its attributes.
|
|
||||||
- Inside a subdirectory, if there is non nix code, it will be in a `config` folder.
|
|
||||||
- Every module should not do anything if imported. An enable option should be toggled
|
|
||||||
for it to have any effect.
|
|
||||||
- Any nix file that represents a module should be named `default.nix` (a nix file
|
|
||||||
which is imported directly can be called anything else alongside `default.nix`)
|
|
||||||
|
|
||||||
### Flake Location
|
### Flake Location
|
||||||
|
|
||||||
|
@ -48,40 +38,58 @@ echo "$FLAKE" # /home/matt/.nix
|
||||||
sudo ln -sf /home/matt/.nix /etc/nixos
|
sudo ln -sf /home/matt/.nix /etc/nixos
|
||||||
```
|
```
|
||||||
|
|
||||||
### Subdirectories
|
### Flake Outputs
|
||||||
|
|
||||||
| Output / Directory | Description |
|
| Output | Description |
|
||||||
| -------------------- | ----------- |
|
| ---------------------------------- | ----------- |
|
||||||
| `apps` | [Misc scripts ran from the flake](./apps) |
|
| `nixosConfigurations` | [devices](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/devices)' + ISO's configurations |
|
||||||
| `configurations` | [device, ISO and nix-on-droid configurations](./configurations) |
|
| `nixOnDroidConfigurations.default` | [Nix-On-Droid](https://git.nelim.org/matt1432/nixos-configs/src/branch/master/devices/android)'s configuration |
|
||||||
| `devShells` | [Development shells for a bunch of projects and languages](./devShells) |
|
| `formatter` | I have yet to know if this has any uses but I format with [alejandra](https://github.com/kamadorueda/alejandra) |
|
||||||
| `homeManagerModules` | [Modules made for home-manager](./homeManagerModules) |
|
| `devShells.default` | A dev shell to build an ISO from the live-image nixosConfiguration |
|
||||||
| `inputs` | [Pre-evaluated flake inputs](./inputs) |
|
|
||||||
| `lib` | [Custom Nix functions made easily available](./lib) |
|
### Flake Inputs
|
||||||
| `modules` | [Modules made for NixOS systems](./modules) |
|
|
||||||
| `nixFastChecks` | [Attribute set of derivations exposed by this flake](./nixFastChecks) |
|
I prefer using a more descriptive format for my inputs like so:
|
||||||
| `overlays` | [Nixpkgs overlays](./overlays) |
|
|
||||||
| `packages` | [Some custom packages not available in nixpkgs or modified from it](./packages) |
|
```nix
|
||||||
| `results` | Directory where I neatly keep my result symlinks from `nixFastChecks` |
|
nixpkgs = {
|
||||||
| `scopedPackages` | [Some custom package scopes not available in nixpkgs or modified from it](./scopedPackages) |
|
type = "github";
|
||||||
|
owner = "NixOS";
|
||||||
|
repo = "nixpkgs";
|
||||||
|
|
||||||
|
# Branch name
|
||||||
|
ref = "nixos-unstable";
|
||||||
|
|
||||||
|
# Pin this input to a specific commit
|
||||||
|
rev = "842d9d80cfd4560648c785f8a4e6f3b096790e19";
|
||||||
|
};
|
||||||
|
```
|
||||||
|
|
||||||
|
to make it more clear what is what in the flake URI
|
||||||
|
|
||||||
|
I also have a long list of inputs with `flake = false;` because
|
||||||
|
it makes it easier to update non-flake custom packages or overlays
|
||||||
|
to have the latest git. I make sure to end the names of these inputs
|
||||||
|
with `src` to make it clear what they are.
|
||||||
|
|
||||||
### Secrets
|
### Secrets
|
||||||
|
|
||||||
All my secrets are in a private git repo that makes use of
|
All my secrets are in a private git repo that makes use of
|
||||||
[sops-nix](https://github.com/Mic92/sops-nix).
|
[sops-nix](https://github.com/Mic92/sops-nix).
|
||||||
I generate `.sops.yaml` from `.sops.nix`:
|
I only use secrets stored in `JSON` and generate `.sops.yaml`
|
||||||
|
from `.sops.nix`:
|
||||||
|
|
||||||
```nix
|
```nix
|
||||||
let
|
let
|
||||||
wim = "somekey";
|
wim = "somekey";
|
||||||
binto = "somekey2";
|
oksys = "somekey2";
|
||||||
in {
|
in {
|
||||||
creation_rules = [
|
creation_rules = [
|
||||||
{
|
{
|
||||||
path_regex = "secrets/[^/]+\\.(yaml|json|env|ini)$";
|
path_regex = "secrets/[^/]+\\.(yaml|json|env|ini)$";
|
||||||
key_groups = [
|
key_groups = [
|
||||||
{
|
{
|
||||||
age = [wim binto];
|
age = [wim oksys];
|
||||||
}
|
}
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
@ -97,4 +105,6 @@ and this shell command:
|
||||||
nix eval --json --file ./.sops.nix | remarshal --if json --of yaml > .sops.yaml
|
nix eval --json --file ./.sops.nix | remarshal --if json --of yaml > .sops.yaml
|
||||||
```
|
```
|
||||||
|
|
||||||
TLDR: I **[hate](https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell)** YAML
|
TLDR: I
|
||||||
|
**[hate](https://ruudvanasseldonk.com/2023/01/11/the-yaml-document-from-hell)**
|
||||||
|
YAML
|
||||||
|
|
110
_outputs.nix
110
_outputs.nix
|
@ -1,110 +0,0 @@
|
||||||
{
|
|
||||||
inputs = import ./inputs;
|
|
||||||
|
|
||||||
outputs = inputs @ {
|
|
||||||
self,
|
|
||||||
systems,
|
|
||||||
nixpkgs,
|
|
||||||
secrets,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (self.lib) mkNixOS mkNixOnDroid mkPkgs;
|
|
||||||
|
|
||||||
perSystem = attrs:
|
|
||||||
nixpkgs.lib.genAttrs (import systems) (system:
|
|
||||||
attrs (mkPkgs {inherit system nixpkgs;}));
|
|
||||||
in {
|
|
||||||
lib = import ./lib {inherit inputs perSystem;};
|
|
||||||
|
|
||||||
nixOnDroidConfigurations.default =
|
|
||||||
mkNixOnDroid [./configurations/android];
|
|
||||||
|
|
||||||
nixosConfigurations = {
|
|
||||||
# Desktops
|
|
||||||
wim = mkNixOS {
|
|
||||||
extraModules = [
|
|
||||||
./configurations/wim
|
|
||||||
secrets.nixosModules.default
|
|
||||||
];
|
|
||||||
};
|
|
||||||
binto = mkNixOS {
|
|
||||||
cudaSupport = true;
|
|
||||||
extraModules = [./configurations/binto];
|
|
||||||
};
|
|
||||||
|
|
||||||
bbsteamie = mkNixOS {
|
|
||||||
mainUser = "mariah";
|
|
||||||
extraModules = [./configurations/bbsteamie];
|
|
||||||
};
|
|
||||||
|
|
||||||
# NAS
|
|
||||||
nos = mkNixOS {
|
|
||||||
cudaSupport = true;
|
|
||||||
extraModules = [
|
|
||||||
./configurations/nos
|
|
||||||
secrets.nixosModules.nos
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Build / test server
|
|
||||||
servivi = mkNixOS {
|
|
||||||
extraModules = [
|
|
||||||
./configurations/servivi
|
|
||||||
secrets.nixosModules.servivi
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Home-assistant
|
|
||||||
homie = mkNixOS {
|
|
||||||
extraModules = [
|
|
||||||
./configurations/homie
|
|
||||||
secrets.nixosModules.homie
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
# Cluster
|
|
||||||
thingone = mkNixOS {
|
|
||||||
extraModules = [
|
|
||||||
(import ./configurations/cluster "thingone")
|
|
||||||
secrets.nixosModules.thingy
|
|
||||||
];
|
|
||||||
};
|
|
||||||
thingtwo = mkNixOS {
|
|
||||||
extraModules = [
|
|
||||||
(import ./configurations/cluster "thingtwo")
|
|
||||||
secrets.nixosModules.thingy
|
|
||||||
];
|
|
||||||
};
|
|
||||||
|
|
||||||
live-image = mkNixOS {
|
|
||||||
mainUser = "nixos";
|
|
||||||
extraModules = [./configurations/live-image];
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
# For nix-fast-build. I use a custom output to alleviate eval time of this flake. ie. when doing nix flake show
|
|
||||||
nixFastChecks = import ./nixFastChecks {inherit perSystem self;};
|
|
||||||
|
|
||||||
homeManagerModules = import ./homeManagerModules {inherit self;};
|
|
||||||
|
|
||||||
nixosModules = import ./modules {inherit self;};
|
|
||||||
|
|
||||||
overlays = import ./overlays {inherit self;};
|
|
||||||
|
|
||||||
apps =
|
|
||||||
perSystem (pkgs:
|
|
||||||
import ./apps {inherit pkgs self;});
|
|
||||||
|
|
||||||
appsPackages = perSystem (pkgs: pkgs.appsPackages);
|
|
||||||
|
|
||||||
devShells =
|
|
||||||
perSystem (pkgs:
|
|
||||||
import ./devShells {inherit pkgs self;});
|
|
||||||
|
|
||||||
packages = perSystem (pkgs: pkgs.selfPackages);
|
|
||||||
|
|
||||||
scopedPackages = perSystem (pkgs: pkgs.scopedPackages);
|
|
||||||
|
|
||||||
formatter = perSystem (pkgs: pkgs.alejandra);
|
|
||||||
};
|
|
||||||
}
|
|
|
@ -1,14 +0,0 @@
|
||||||
# Apps
|
|
||||||
|
|
||||||
This directory contains every derivations for apps exposed by this flake.
|
|
||||||
|
|
||||||
## List of my apps found in `self.apps`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
| `extract-subs` | Extract all `srt` subtitle files from a `mkv` video with the appropriate name. |
|
|
||||||
| `gen-docs` | Generates the READMEs in this repository from nix attributes. |
|
|
||||||
| `list2series` | Converts a Komga read list into a comics series for reading with mihon. |
|
|
||||||
| `mc-mods` | Checks if a list of mods have a version available for a specific Minecraft version and a specific loader. |
|
|
||||||
| `pin-inputs` | Takes a list of inputs to pin to their current rev in `flake.lock`. |
|
|
||||||
| `update-sources` | Updates all derivation sources in this repository and generates a commit message for the changes made. |
|
|
|
@ -1,61 +0,0 @@
|
||||||
{
|
|
||||||
lib,
|
|
||||||
src,
|
|
||||||
npmDepsHash,
|
|
||||||
runtimeInputs,
|
|
||||||
buildNpmPackage,
|
|
||||||
meta,
|
|
||||||
makeWrapper,
|
|
||||||
nodejs_latest,
|
|
||||||
jq,
|
|
||||||
...
|
|
||||||
}: let
|
|
||||||
inherit (lib) boolToString concatMapStringsSep concatStringsSep mapAttrsToList;
|
|
||||||
inherit (builtins) fromJSON isBool readFile;
|
|
||||||
|
|
||||||
packageJSON = fromJSON (readFile "${src}/package.json");
|
|
||||||
tsconfig = fromJSON (readFile ./config/tsconfig.base.json);
|
|
||||||
|
|
||||||
pname = packageJSON.name;
|
|
||||||
inherit (packageJSON) version;
|
|
||||||
in
|
|
||||||
buildNpmPackage {
|
|
||||||
inherit pname version src runtimeInputs npmDepsHash;
|
|
||||||
|
|
||||||
prePatch = ''
|
|
||||||
# Patch tsconfig
|
|
||||||
mv ./tsconfig.json ./project.json
|
|
||||||
sed 's/^ *\/\/.*//' ${./config/tsconfig.base.json} > ./base.json
|
|
||||||
${jq}/bin/jq -sr '.[0] * .[1] | del(.extends)' ./project.json ./base.json > ./tsconfig.json
|
|
||||||
rm base.json project.json
|
|
||||||
'';
|
|
||||||
|
|
||||||
nativeBuildInputs = [makeWrapper];
|
|
||||||
|
|
||||||
postInstall = ''
|
|
||||||
wrapProgram $out/bin/${pname} \
|
|
||||||
--prefix PATH : ${concatMapStringsSep ":" (p: p + "/bin") runtimeInputs}
|
|
||||||
'';
|
|
||||||
|
|
||||||
doCheck = true;
|
|
||||||
|
|
||||||
checkPhase = ''
|
|
||||||
runHook preCheck
|
|
||||||
|
|
||||||
npx tsc ${concatStringsSep " " (mapAttrsToList (n: v:
|
|
||||||
if n == "lib"
|
|
||||||
then concatMapStringsSep " " (x: "--lib ${x}") v
|
|
||||||
else "--${n} ${
|
|
||||||
if isBool v
|
|
||||||
then boolToString v
|
|
||||||
else toString v
|
|
||||||
}")
|
|
||||||
tsconfig.compilerOptions)} src/app.ts
|
|
||||||
|
|
||||||
runHook postCheck
|
|
||||||
'';
|
|
||||||
|
|
||||||
nodejs = nodejs_latest;
|
|
||||||
|
|
||||||
meta = {mainProgram = pname;} // meta;
|
|
||||||
}
|
|
|
@ -1,2 +0,0 @@
|
||||||
use flake $FLAKE#node
|
|
||||||
npm ci
|
|
|
@ -1,451 +0,0 @@
|
||||||
import eslint from '@eslint/js';
|
|
||||||
import jsdoc from 'eslint-plugin-jsdoc';
|
|
||||||
import stylistic from '@stylistic/eslint-plugin';
|
|
||||||
import tseslint from 'typescript-eslint';
|
|
||||||
|
|
||||||
|
|
||||||
export default tseslint.config({
|
|
||||||
files: ['**/*.js', '**/*.ts'],
|
|
||||||
ignores: ['node_modules/**', 'types/**'],
|
|
||||||
|
|
||||||
extends: [
|
|
||||||
eslint.configs.recommended,
|
|
||||||
jsdoc.configs['flat/recommended-typescript'],
|
|
||||||
stylistic.configs['recommended-flat'],
|
|
||||||
...tseslint.configs.recommended,
|
|
||||||
...tseslint.configs.stylistic,
|
|
||||||
],
|
|
||||||
|
|
||||||
rules: {
|
|
||||||
// JSDoc settings
|
|
||||||
'jsdoc/tag-lines': ['warn', 'any', { startLines: 1 }],
|
|
||||||
'jsdoc/check-line-alignment': ['warn', 'always', {
|
|
||||||
tags: ['param', 'arg', 'argument', 'property', 'prop'],
|
|
||||||
}],
|
|
||||||
'jsdoc/no-types': 'off',
|
|
||||||
|
|
||||||
// Newer settings
|
|
||||||
'@typescript-eslint/no-extraneous-class': ['off'],
|
|
||||||
'@typescript-eslint/no-implied-eval': ['off'],
|
|
||||||
'class-methods-use-this': 'off',
|
|
||||||
'@stylistic/no-multiple-empty-lines': 'off',
|
|
||||||
|
|
||||||
// Pre-flat config
|
|
||||||
'@typescript-eslint/no-unused-vars': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
args: 'all',
|
|
||||||
argsIgnorePattern: '^_',
|
|
||||||
caughtErrors: 'all',
|
|
||||||
caughtErrorsIgnorePattern: '^_',
|
|
||||||
destructuredArrayIgnorePattern: '^_',
|
|
||||||
varsIgnorePattern: '^_',
|
|
||||||
ignoreRestSiblings: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
|
|
||||||
'array-callback-return': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
allowImplicit: true,
|
|
||||||
checkForEach: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-constructor-return': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-unreachable-loop': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
ignore: [
|
|
||||||
'ForInStatement',
|
|
||||||
'ForOfStatement',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-use-before-define': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
functions: false,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'block-scoped-var': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'curly': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'default-case-last': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'default-param-last': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'eqeqeq': [
|
|
||||||
'error',
|
|
||||||
'smart',
|
|
||||||
],
|
|
||||||
'func-names': [
|
|
||||||
'warn',
|
|
||||||
'never',
|
|
||||||
],
|
|
||||||
'func-style': [
|
|
||||||
'warn',
|
|
||||||
'expression',
|
|
||||||
],
|
|
||||||
'logical-assignment-operators': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'no-array-constructor': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-empty-function': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-empty-static-block': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-extend-native': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-extra-bind': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-implicit-coercion': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-iterator': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-labels': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-lone-blocks': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-lonely-if': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-loop-func': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-magic-numbers': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
ignore: [
|
|
||||||
-1,
|
|
||||||
0.1,
|
|
||||||
0,
|
|
||||||
1,
|
|
||||||
2,
|
|
||||||
3,
|
|
||||||
4,
|
|
||||||
5,
|
|
||||||
10,
|
|
||||||
12,
|
|
||||||
33,
|
|
||||||
66,
|
|
||||||
100,
|
|
||||||
255,
|
|
||||||
360,
|
|
||||||
450,
|
|
||||||
500,
|
|
||||||
1000,
|
|
||||||
],
|
|
||||||
ignoreDefaultValues: true,
|
|
||||||
ignoreClassFieldInitialValues: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-multi-assign': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-new-wrappers': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-object-constructor': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-proto': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-return-assign': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-sequences': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-shadow': [
|
|
||||||
'error',
|
|
||||||
{
|
|
||||||
builtinGlobals: true,
|
|
||||||
allow: [
|
|
||||||
'Window',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'no-undef-init': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-undefined': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-useless-constructor': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-useless-escape': [
|
|
||||||
'off',
|
|
||||||
],
|
|
||||||
'no-useless-return': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-var': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'no-void': [
|
|
||||||
'off',
|
|
||||||
],
|
|
||||||
'no-with': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'object-shorthand': [
|
|
||||||
'error',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'one-var': [
|
|
||||||
'error',
|
|
||||||
'never',
|
|
||||||
],
|
|
||||||
'operator-assignment': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'prefer-arrow-callback': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'prefer-const': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'prefer-object-has-own': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'prefer-regex-literals': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'prefer-template': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'no-prototype-builtins': 'off',
|
|
||||||
'@typescript-eslint/no-var-requires': [
|
|
||||||
'off',
|
|
||||||
],
|
|
||||||
'@stylistic/array-bracket-newline': [
|
|
||||||
'warn',
|
|
||||||
'consistent',
|
|
||||||
],
|
|
||||||
'@stylistic/array-bracket-spacing': [
|
|
||||||
'warn',
|
|
||||||
'never',
|
|
||||||
],
|
|
||||||
'@stylistic/arrow-parens': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'@stylistic/brace-style': [
|
|
||||||
'warn',
|
|
||||||
'stroustrup',
|
|
||||||
],
|
|
||||||
'@stylistic/comma-dangle': [
|
|
||||||
'warn',
|
|
||||||
'always-multiline',
|
|
||||||
],
|
|
||||||
'@stylistic/comma-spacing': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
before: false,
|
|
||||||
after: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/comma-style': [
|
|
||||||
'error',
|
|
||||||
'last',
|
|
||||||
],
|
|
||||||
'@stylistic/dot-location': [
|
|
||||||
'error',
|
|
||||||
'property',
|
|
||||||
],
|
|
||||||
'@stylistic/function-call-argument-newline': [
|
|
||||||
'warn',
|
|
||||||
'consistent',
|
|
||||||
],
|
|
||||||
'@stylistic/function-paren-newline': [
|
|
||||||
'warn',
|
|
||||||
'consistent',
|
|
||||||
],
|
|
||||||
'@stylistic/indent': [
|
|
||||||
'warn',
|
|
||||||
4,
|
|
||||||
{
|
|
||||||
SwitchCase: 1,
|
|
||||||
ignoreComments: true,
|
|
||||||
ignoredNodes: ['TemplateLiteral > *'],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/key-spacing': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
beforeColon: false,
|
|
||||||
afterColon: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/keyword-spacing': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
before: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/linebreak-style': [
|
|
||||||
'error',
|
|
||||||
'unix',
|
|
||||||
],
|
|
||||||
'@stylistic/lines-between-class-members': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
{
|
|
||||||
exceptAfterSingleLine: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/max-len': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
code: 105,
|
|
||||||
ignoreComments: true,
|
|
||||||
ignoreTrailingComments: true,
|
|
||||||
ignoreUrls: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/multiline-ternary': [
|
|
||||||
'warn',
|
|
||||||
'always-multiline',
|
|
||||||
],
|
|
||||||
'@stylistic/new-parens': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'@stylistic/no-mixed-operators': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/no-mixed-spaces-and-tabs': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'@stylistic/no-multi-spaces': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'@stylistic/no-tabs': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'@stylistic/no-trailing-spaces': [
|
|
||||||
'error',
|
|
||||||
],
|
|
||||||
'@stylistic/no-whitespace-before-property': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/nonblock-statement-body-position': [
|
|
||||||
'error',
|
|
||||||
'below',
|
|
||||||
],
|
|
||||||
'@stylistic/object-curly-newline': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
consistent: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/object-curly-spacing': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'@stylistic/operator-linebreak': [
|
|
||||||
'warn',
|
|
||||||
'after',
|
|
||||||
],
|
|
||||||
'@stylistic/padded-blocks': [
|
|
||||||
'error',
|
|
||||||
'never',
|
|
||||||
],
|
|
||||||
'@stylistic/padding-line-between-statements': [
|
|
||||||
'warn',
|
|
||||||
{
|
|
||||||
blankLine: 'always',
|
|
||||||
prev: '*',
|
|
||||||
next: 'return',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
blankLine: 'always',
|
|
||||||
prev: [
|
|
||||||
'const',
|
|
||||||
'let',
|
|
||||||
'var',
|
|
||||||
],
|
|
||||||
next: '*',
|
|
||||||
},
|
|
||||||
{
|
|
||||||
blankLine: 'any',
|
|
||||||
prev: [
|
|
||||||
'const',
|
|
||||||
'let',
|
|
||||||
'var',
|
|
||||||
],
|
|
||||||
next: [
|
|
||||||
'const',
|
|
||||||
'let',
|
|
||||||
'var',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
blankLine: 'always',
|
|
||||||
prev: [
|
|
||||||
'case',
|
|
||||||
'default',
|
|
||||||
],
|
|
||||||
next: '*',
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/quote-props': [
|
|
||||||
'error',
|
|
||||||
'consistent-as-needed',
|
|
||||||
],
|
|
||||||
'@stylistic/quotes': [
|
|
||||||
'error',
|
|
||||||
'single',
|
|
||||||
{
|
|
||||||
avoidEscape: true,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
'@stylistic/semi': [
|
|
||||||
'error',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'@stylistic/semi-spacing': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/space-before-blocks': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/space-before-function-paren': [
|
|
||||||
'warn',
|
|
||||||
'never',
|
|
||||||
],
|
|
||||||
'@stylistic/space-infix-ops': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/spaced-comment': [
|
|
||||||
'warn',
|
|
||||||
'always',
|
|
||||||
],
|
|
||||||
'@stylistic/switch-colon-spacing': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
'@stylistic/wrap-regex': [
|
|
||||||
'warn',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
});
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from './eslint.config';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
1737
apps/config/package-lock.json
generated
1737
apps/config/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,16 +0,0 @@
|
||||||
{
|
|
||||||
"name": "eslint-conf",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"type": "module",
|
|
||||||
"exports": "./index.ts",
|
|
||||||
"dependencies": {
|
|
||||||
"@eslint/js": "9.28.0",
|
|
||||||
"@stylistic/eslint-plugin": "4.4.0",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"eslint-plugin-jsdoc": "50.7.1",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"pkg-types": "2.1.0",
|
|
||||||
"typescript": "5.8.3",
|
|
||||||
"typescript-eslint": "8.33.1"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"compilerOptions": {
|
|
||||||
"target": "ESNext",
|
|
||||||
"lib": [
|
|
||||||
"ESNext"
|
|
||||||
],
|
|
||||||
"module": "preserve",
|
|
||||||
"moduleResolution": "bundler",
|
|
||||||
"baseUrl": ".",
|
|
||||||
"noEmit": true,
|
|
||||||
"newLine": "LF",
|
|
||||||
"esModuleInterop": true,
|
|
||||||
"allowSyntheticDefaultImports": true,
|
|
||||||
"forceConsistentCasingInFileNames": true,
|
|
||||||
"isolatedModules": true,
|
|
||||||
"skipLibCheck": true,
|
|
||||||
"strict": true,
|
|
||||||
"noImplicitAny": false
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "./tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,9 +0,0 @@
|
||||||
{pkgs, ...}: let
|
|
||||||
inherit (pkgs.lib) getExe mapAttrs;
|
|
||||||
|
|
||||||
mkApp = pkg: {
|
|
||||||
program = getExe pkg;
|
|
||||||
type = "app";
|
|
||||||
};
|
|
||||||
in
|
|
||||||
mapAttrs (n: v: mkApp v) pkgs.appsPackages
|
|
|
@ -1,3 +0,0 @@
|
||||||
use flake $FLAKE#subtitles-dev
|
|
||||||
(cd ../config; npm ci)
|
|
||||||
npm ci
|
|
|
@ -1,17 +0,0 @@
|
||||||
{
|
|
||||||
buildApp,
|
|
||||||
ffmpeg-full,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
buildApp {
|
|
||||||
src = ./.;
|
|
||||||
npmDepsHash = "sha256-eU6zgcenSbJHCxiFiNyM894Gzt3U8DRd/wpSAziqE6k=";
|
|
||||||
|
|
||||||
runtimeInputs = [
|
|
||||||
ffmpeg-full
|
|
||||||
];
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Extract all `srt` subtitle files from a `mkv` video with the appropriate name.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from 'eslint-conf';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
1548
apps/extract-subs/package-lock.json
generated
1548
apps/extract-subs/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"name": "extract-subs",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bin": "out/bin/app.cjs",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/fluent-ffmpeg": "2.1.27",
|
|
||||||
"fluent-ffmpeg": "2.1.3",
|
|
||||||
"@types/node": "22.15.29",
|
|
||||||
"esbuild": "0.25.5",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint-conf": "file:../config"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,157 +0,0 @@
|
||||||
import { spawnSync as spawn } from 'child_process';
|
|
||||||
|
|
||||||
import ffprobe from './ffprobe';
|
|
||||||
import { ISO6393To1 } from './lang-codes';
|
|
||||||
|
|
||||||
/* Types */
|
|
||||||
import { FfprobeStream } from 'fluent-ffmpeg';
|
|
||||||
|
|
||||||
|
|
||||||
const SPAWN_OPTS = {
|
|
||||||
stdio: [process.stdin, process.stdout, process.stderr],
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* These are the cli arguments
|
|
||||||
*
|
|
||||||
* @param videoPath the directory in which we want to sync the subtitles
|
|
||||||
* @param languages a comma-separated list of languages (3 letters) to sync the subtitles
|
|
||||||
*/
|
|
||||||
const video = process.argv[2];
|
|
||||||
const languages = process.argv[3]?.split(',');
|
|
||||||
|
|
||||||
|
|
||||||
// Global Vars
|
|
||||||
const subIndexes: number[] = [];
|
|
||||||
let videoPath: string;
|
|
||||||
let baseName: string;
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the relative path to the subtitle file of a ffmpeg stream.
|
|
||||||
*
|
|
||||||
* @param sub the stream of the subtitles to extract
|
|
||||||
* @returns the path of the subtitle file
|
|
||||||
*/
|
|
||||||
const getSubPath = (sub: FfprobeStream): string => {
|
|
||||||
const language = ISO6393To1.get(sub.tags.language);
|
|
||||||
|
|
||||||
const forced = sub.disposition?.forced === 0 ?
|
|
||||||
'' :
|
|
||||||
'.forced';
|
|
||||||
|
|
||||||
const hearingImpaired = sub.disposition?.hearing_impaired === 0 ?
|
|
||||||
'' :
|
|
||||||
'.sdh';
|
|
||||||
|
|
||||||
return `${baseName}${forced}.${language}${hearingImpaired}.srt`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Removes all subtitles streams from the video file.
|
|
||||||
*/
|
|
||||||
const removeContainerSubs = (): void => {
|
|
||||||
spawn('mv', [
|
|
||||||
videoPath,
|
|
||||||
`${videoPath}.bak`,
|
|
||||||
], SPAWN_OPTS);
|
|
||||||
|
|
||||||
spawn('ffmpeg', [
|
|
||||||
'-i', `${videoPath}.bak`,
|
|
||||||
'-map', '0',
|
|
||||||
...subIndexes.map((i) => ['-map', `-0:${i}`]).flat(),
|
|
||||||
'-c', 'copy', videoPath,
|
|
||||||
], SPAWN_OPTS);
|
|
||||||
|
|
||||||
spawn('rm', [
|
|
||||||
`${videoPath}.bak`,
|
|
||||||
], SPAWN_OPTS);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Extracts a sub of a video file to a subtitle file.
|
|
||||||
*
|
|
||||||
* @param sub the stream of the subtitles to extract
|
|
||||||
*/
|
|
||||||
const extractSub = (sub: FfprobeStream): void => {
|
|
||||||
const subFile = getSubPath(sub);
|
|
||||||
|
|
||||||
spawn('ffmpeg', [
|
|
||||||
'-i', videoPath,
|
|
||||||
'-map', `0:${sub.index}`, subFile,
|
|
||||||
], SPAWN_OPTS);
|
|
||||||
|
|
||||||
subIndexes.push(sub.index);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Sorts the list of streams to only keep subtitles
|
|
||||||
* that can be extracted.
|
|
||||||
*
|
|
||||||
* @param lang the language of the subtitles
|
|
||||||
* @param streams the streams
|
|
||||||
* @returns the streams that represent subtitles
|
|
||||||
*/
|
|
||||||
const findSubs = (
|
|
||||||
lang: string,
|
|
||||||
streams: FfprobeStream[],
|
|
||||||
): FfprobeStream[] => {
|
|
||||||
const subs = streams.filter((s) => s.tags?.language &&
|
|
||||||
s.tags.language === lang &&
|
|
||||||
s.codec_type === 'subtitle');
|
|
||||||
|
|
||||||
const pgs = subs.filter((s) => s.codec_name === 'hdmv_pgs_subtitle');
|
|
||||||
|
|
||||||
// If we only have PGS subs, warn user
|
|
||||||
if (pgs.length === subs.length) {
|
|
||||||
console.warn(`No SRT subtitle tracks were found for ${lang}`);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Remove PGS streams from subs
|
|
||||||
return subs.filter((s) => s.codec_name !== 'hdmv_pgs_subtitle');
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Where the magic happens.
|
|
||||||
*/
|
|
||||||
const main = async(): Promise<void> => {
|
|
||||||
// Get rid of video extension
|
|
||||||
baseName = videoPath.split('/').at(-1)!.replace(/\.[^.]*$/, '');
|
|
||||||
|
|
||||||
// ffprobe the video file to see available sub tracks
|
|
||||||
const data = await ffprobe(videoPath);
|
|
||||||
|
|
||||||
if (!data?.streams) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Check for languages wanted
|
|
||||||
languages.forEach((lang) => {
|
|
||||||
const subs = findSubs(lang, data.streams);
|
|
||||||
|
|
||||||
if (subs.length === 0) {
|
|
||||||
console.warn(`No subtitle tracks were found for ${lang}`);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Extract all subs
|
|
||||||
subs.forEach((sub) => {
|
|
||||||
extractSub(sub);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
removeContainerSubs();
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
// Check if there are 2 params
|
|
||||||
if (video && languages) {
|
|
||||||
videoPath = video;
|
|
||||||
main();
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.error('Error: no argument passed');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
|
@ -1,8 +0,0 @@
|
||||||
import Ffmpeg from 'fluent-ffmpeg';
|
|
||||||
|
|
||||||
|
|
||||||
export default (videoPath: string) => new Promise<Ffmpeg.FfprobeData>((resolve) => {
|
|
||||||
Ffmpeg.ffprobe(videoPath, (_e, data) => {
|
|
||||||
resolve(data);
|
|
||||||
});
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "../config/tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,15 +0,0 @@
|
||||||
{
|
|
||||||
writeShellApplication,
|
|
||||||
jq,
|
|
||||||
pandoc,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
writeShellApplication {
|
|
||||||
name = "gen-docs";
|
|
||||||
runtimeInputs = [jq pandoc];
|
|
||||||
text = builtins.readFile ./script.sh;
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Generates the READMEs in this repository from nix attributes.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
attr: selfPath: let
|
|
||||||
inherit (builtins) mapAttrs replaceStrings;
|
|
||||||
|
|
||||||
modules = import "${selfPath}/${attr}" {description = true;};
|
|
||||||
|
|
||||||
trimNewlines = s: replaceStrings ["\n"] [" "] s;
|
|
||||||
in {
|
|
||||||
attrs =
|
|
||||||
mapAttrs (_: v: {
|
|
||||||
desc = trimNewlines v;
|
|
||||||
})
|
|
||||||
modules;
|
|
||||||
}
|
|
|
@ -1,12 +0,0 @@
|
||||||
configs: let
|
|
||||||
inherit (builtins) mapAttrs replaceStrings;
|
|
||||||
|
|
||||||
trimNewlines = s: replaceStrings ["\n"] [" "] s;
|
|
||||||
in {
|
|
||||||
attrs =
|
|
||||||
mapAttrs (_: v: {
|
|
||||||
roleDesc = trimNewlines (v.config.meta.roleDescription or "");
|
|
||||||
hwDesc = trimNewlines (v.config.meta.hardwareDescription or "");
|
|
||||||
})
|
|
||||||
configs;
|
|
||||||
}
|
|
|
@ -1,13 +0,0 @@
|
||||||
x: let
|
|
||||||
inherit (builtins) currentSystem mapAttrs removeAttrs replaceStrings;
|
|
||||||
|
|
||||||
trimNewlines = s: replaceStrings ["\n"] [" "] s;
|
|
||||||
packages = removeAttrs x.${currentSystem} ["default"];
|
|
||||||
in {
|
|
||||||
attrs =
|
|
||||||
mapAttrs (_: v: {
|
|
||||||
desc = trimNewlines (v.meta.description or "");
|
|
||||||
homepage = v.meta.homepage or "";
|
|
||||||
})
|
|
||||||
packages;
|
|
||||||
}
|
|
|
@ -1,31 +0,0 @@
|
||||||
attr: selfPath: let
|
|
||||||
inherit (builtins) currentSystem getFlake mapAttrs removeAttrs replaceStrings;
|
|
||||||
|
|
||||||
self = getFlake selfPath;
|
|
||||||
scopes = ((import "${selfPath}/${attr}" {description = true;}) {} {}).scopedPackages;
|
|
||||||
|
|
||||||
trimNewlines = s: replaceStrings ["\n"] [" "] s;
|
|
||||||
in {
|
|
||||||
attrs =
|
|
||||||
mapAttrs (n: v: {
|
|
||||||
desc = trimNewlines v;
|
|
||||||
packages = let
|
|
||||||
scopePkgs = removeAttrs self.${attr}.${currentSystem}.${n} [
|
|
||||||
"buildFirefoxXpiAddon"
|
|
||||||
"callPackage"
|
|
||||||
"newScope"
|
|
||||||
"override"
|
|
||||||
"overrideDerivation"
|
|
||||||
"overrideScope"
|
|
||||||
"packages"
|
|
||||||
"recurseForDerivations"
|
|
||||||
];
|
|
||||||
in
|
|
||||||
mapAttrs (_: pkg: {
|
|
||||||
desc = trimNewlines (pkg.meta.description or "");
|
|
||||||
homepage = pkg.meta.homepage or "";
|
|
||||||
})
|
|
||||||
scopePkgs;
|
|
||||||
})
|
|
||||||
scopes;
|
|
||||||
}
|
|
|
@ -1,43 +0,0 @@
|
||||||
substituteDerivs() {
|
|
||||||
echo '' | pandoc --metadata-file <(
|
|
||||||
nix eval \
|
|
||||||
--impure \
|
|
||||||
--json \
|
|
||||||
"$FLAKE"#"$1" \
|
|
||||||
--apply "import \"$FLAKE/apps/gen-docs/$3.nix\"" |
|
|
||||||
jq -r
|
|
||||||
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$2.md" -o "$FLAKE/$2/README.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
substituteAttrs() {
|
|
||||||
echo '' | pandoc --metadata-file <(
|
|
||||||
nix eval \
|
|
||||||
--impure \
|
|
||||||
--json \
|
|
||||||
--expr "\"$FLAKE\"" \
|
|
||||||
--apply "(import \"$FLAKE/apps/gen-docs/getAttrsMeta.nix\") \"$1\"" |
|
|
||||||
jq -r
|
|
||||||
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$1.md" -o "$FLAKE/$1/README.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
substituteScopes() {
|
|
||||||
echo '' | pandoc --metadata-file <(
|
|
||||||
nix eval \
|
|
||||||
--impure \
|
|
||||||
--json \
|
|
||||||
--expr "\"$FLAKE\"" \
|
|
||||||
--apply "(import \"$FLAKE/apps/gen-docs/getScopesMeta.nix\") \"$1\"" |
|
|
||||||
jq -r
|
|
||||||
) -t markdown --template "$FLAKE/apps/gen-docs/templates/$1.md" -o "$FLAKE/$1/README.md"
|
|
||||||
}
|
|
||||||
|
|
||||||
substituteDerivs "appsPackages" "apps" "getPackageMeta"
|
|
||||||
substituteDerivs "nixosConfigurations" "configurations" "getConfigMeta"
|
|
||||||
substituteDerivs "devShells" "devShells" "getPackageMeta"
|
|
||||||
substituteDerivs "packages" "packages" "getPackageMeta"
|
|
||||||
|
|
||||||
substituteAttrs "modules"
|
|
||||||
substituteAttrs "homeManagerModules"
|
|
||||||
substituteAttrs "overlays"
|
|
||||||
|
|
||||||
substituteScopes "scopedPackages"
|
|
|
@ -1,11 +0,0 @@
|
||||||
# Apps
|
|
||||||
|
|
||||||
This directory contains every derivations for apps exposed by this flake.
|
|
||||||
|
|
||||||
## List of my apps found in `self.apps`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,13 +0,0 @@
|
||||||
# NixosConfigurations
|
|
||||||
|
|
||||||
This directory contains every device's main configuration file, their `hardware-configuration.nix` and some custom modules
|
|
||||||
unique to them.
|
|
||||||
|
|
||||||
## List of my devices
|
|
||||||
|
|
||||||
| Name | Model / Specs | Description |
|
|
||||||
| --------- | ------------- | ------------------------------------------------------------------------------------------------ |
|
|
||||||
| `android` | OnePlus 9 Pro | [Nix-On-Droid](https://github.com/nix-community/nix-on-droid) configuration for my OnePlus 9 Pro |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.hwDesc/nowrap$ | $it.value.roleDesc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,11 +0,0 @@
|
||||||
# DevShells
|
|
||||||
|
|
||||||
This directory contains every derivations for devShells exposed by this flake.
|
|
||||||
|
|
||||||
## List of my devShells found in `self.devShells`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,11 +0,0 @@
|
||||||
# HomeManagerModules
|
|
||||||
|
|
||||||
This directory contains every home-manager modules exposed by this flake.
|
|
||||||
|
|
||||||
## List of my home-manager modules found in `self.homeManagerModules`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,11 +0,0 @@
|
||||||
# NixosModules
|
|
||||||
|
|
||||||
This directory contains every modules for NixOS exposed by this flake.
|
|
||||||
|
|
||||||
## List of my modules found in `self.nixosModules`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,11 +0,0 @@
|
||||||
# Overlays
|
|
||||||
|
|
||||||
This directory contains every overlay exposed by this flake.
|
|
||||||
|
|
||||||
## List of my overlays found in `self.overlays`
|
|
||||||
|
|
||||||
| Name | Description |
|
|
||||||
| ---- | ----------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,11 +0,0 @@
|
||||||
# Packages
|
|
||||||
|
|
||||||
This directory contains every derivations for packages exposed by this flake.
|
|
||||||
|
|
||||||
## List of my packages found in `self.packages`
|
|
||||||
|
|
||||||
| Name | Description | Homepage |
|
|
||||||
| ---- | ----------- | -------- |
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ | $it.value.homepage/nowrap$ |
|
|
||||||
$endfor$
|
|
|
@ -1,18 +0,0 @@
|
||||||
# ScopedPackages
|
|
||||||
|
|
||||||
This directory contains every package scopes exposed by this flake.
|
|
||||||
|
|
||||||
## List of my package scopes found in `self.scopedPackages`
|
|
||||||
|
|
||||||
$for(attrs/pairs)$
|
|
||||||
### $it.key$
|
|
||||||
|
|
||||||
$it.value.desc/nowrap$
|
|
||||||
|
|
||||||
| Name | Description | Homepage |
|
|
||||||
| ---- | ----------- | -------- |
|
|
||||||
$for(it.value.packages/pairs)$
|
|
||||||
| `$it.key$` | $it.value.desc/nowrap$ | $it.value.homepage/nowrap$ |
|
|
||||||
$endfor$
|
|
||||||
|
|
||||||
$endfor$
|
|
|
@ -1,3 +0,0 @@
|
||||||
use flake $FLAKE#node
|
|
||||||
(cd ../config; npm ci)
|
|
||||||
npm ci
|
|
1
apps/list2series/.gitignore
vendored
1
apps/list2series/.gitignore
vendored
|
@ -1 +0,0 @@
|
||||||
.env
|
|
|
@ -1,11 +0,0 @@
|
||||||
{buildApp, ...}:
|
|
||||||
buildApp {
|
|
||||||
src = ./.;
|
|
||||||
npmDepsHash = "sha256-4+JdRDVvr28sw4vsYnhtOY6S8+uKw6NMTb6lpY5T0g4=";
|
|
||||||
|
|
||||||
runtimeInputs = [];
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Converts a Komga read list into a comics series for reading with mihon.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from 'eslint-conf';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
File diff suppressed because it is too large
Load diff
1815
apps/list2series/package-lock.json
generated
1815
apps/list2series/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,21 +0,0 @@
|
||||||
{
|
|
||||||
"name": "list2series",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bin": "out/bin/app.cjs",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "22.15.29",
|
|
||||||
"axios": "1.9.0",
|
|
||||||
"esbuild": "0.25.5",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"pkg-types": "2.1.0",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint-conf": "file:../config"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,354 +0,0 @@
|
||||||
import axios from 'axios';
|
|
||||||
import { linkSync, mkdirSync, readFileSync, rmSync } from 'fs';
|
|
||||||
import { basename } from 'path';
|
|
||||||
|
|
||||||
import {
|
|
||||||
type Book,
|
|
||||||
type ListsJson,
|
|
||||||
type ReadList,
|
|
||||||
type Series,
|
|
||||||
} from './types';
|
|
||||||
|
|
||||||
|
|
||||||
// Examples of calling this script:
|
|
||||||
// $ just l2s copy 0K65Q482KK7SD
|
|
||||||
// $ just l2s meta 0K65Q482KK7SD
|
|
||||||
|
|
||||||
const readNeighborFile = (filename: string) => JSON.parse(
|
|
||||||
readFileSync(`${process.env.FLAKE}/apps/list2series/${filename}`, { encoding: 'utf-8' }),
|
|
||||||
);
|
|
||||||
|
|
||||||
const API = readNeighborFile('.env').API;
|
|
||||||
|
|
||||||
const getListInfo = async(listId: string): Promise<ReadList> => {
|
|
||||||
const res = await axios.request({
|
|
||||||
method: 'get',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: `https://komga.nelim.org/api/v1/readlists/${listId}`,
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSeries = async(seriesTitle: string, operator = true): Promise<Series[]> => {
|
|
||||||
return (await axios.request({
|
|
||||||
method: 'post',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: 'https://komga.nelim.org/api/v1/series/list?unpaged=true',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
condition: {
|
|
||||||
title: {
|
|
||||||
operator: operator ? 'is' : 'isNot',
|
|
||||||
value: seriesTitle,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})).data.content;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getSeriesBooks = async(listName: string, seriesPath: string): Promise<Book[]> => {
|
|
||||||
const thisSeries = (await getSeries('', false)).find((s) => s.url === seriesPath);
|
|
||||||
|
|
||||||
if (!thisSeries) {
|
|
||||||
throw new Error('Series could not be found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Reset Series metadata
|
|
||||||
axios.request({
|
|
||||||
method: 'patch',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: `https://komga.nelim.org/api/v1/series/${thisSeries.id}/metadata`,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
ageRating: null,
|
|
||||||
ageRatingLock: true,
|
|
||||||
alternateTitles: null,
|
|
||||||
alternateTitlesLock: true,
|
|
||||||
genres: null,
|
|
||||||
genresLock: true,
|
|
||||||
language: null,
|
|
||||||
languageLock: true,
|
|
||||||
links: null,
|
|
||||||
linksLock: true,
|
|
||||||
publisherLock: true,
|
|
||||||
readingDirection: 'LEFT_TO_RIGHT',
|
|
||||||
readingDirectionLock: true,
|
|
||||||
sharingLabels: null,
|
|
||||||
sharingLabelsLock: true,
|
|
||||||
status: null,
|
|
||||||
statusLock: true,
|
|
||||||
summary: null,
|
|
||||||
summaryLock: true,
|
|
||||||
tags: null,
|
|
||||||
tagsLock: true,
|
|
||||||
title: listName,
|
|
||||||
titleLock: true,
|
|
||||||
titleSort: listName,
|
|
||||||
titleSortLock: true,
|
|
||||||
totalBookCountLock: true,
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
const books = await axios.request({
|
|
||||||
method: 'post',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: 'https://komga.nelim.org/api/v1/books/list?unpaged=true',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
condition: {
|
|
||||||
seriesId: {
|
|
||||||
operator: 'is',
|
|
||||||
value: thisSeries.id,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
return books.data.content;
|
|
||||||
};
|
|
||||||
|
|
||||||
const getBookInfo = async(id: string): Promise<Book> => {
|
|
||||||
const res = await axios.request({
|
|
||||||
method: 'get',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: `https://komga.nelim.org/api/v1/books/${id}`,
|
|
||||||
headers: {
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
|
|
||||||
return res.data;
|
|
||||||
};
|
|
||||||
|
|
||||||
// There doesn't seem to be a way to wait for the scan to be done
|
|
||||||
const scanLibrary = (): void => {
|
|
||||||
axios.request({
|
|
||||||
method: 'post',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: 'https://komga.nelim.org/api/v1/libraries/0K4QG58XA29DZ/scan',
|
|
||||||
headers: {
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const setBookMetadata = async(i: number, source: Book, target: Book): Promise<void> => {
|
|
||||||
const thisSeries = (await getSeries(source.seriesTitle))[0];
|
|
||||||
|
|
||||||
source.metadata.title = thisSeries.booksCount !== 1 ?
|
|
||||||
`${source.seriesTitle} Issue #${source.metadata.number}` :
|
|
||||||
source.metadata.title = source.seriesTitle;
|
|
||||||
|
|
||||||
source.metadata.number = i.toString();
|
|
||||||
source.metadata.numberSort = i;
|
|
||||||
|
|
||||||
const metadata = JSON.stringify(source.metadata);
|
|
||||||
|
|
||||||
axios.request({
|
|
||||||
method: 'patch',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: `https://komga.nelim.org/api/v1/books/${target.id}/metadata`,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: metadata,
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
const getListBooks = async(listKeyOrId: string): Promise<{
|
|
||||||
list: ReadList
|
|
||||||
seriesPath: string
|
|
||||||
listBooks: Book[]
|
|
||||||
}> => {
|
|
||||||
let listId = listKeyOrId;
|
|
||||||
|
|
||||||
const listMappings = readNeighborFile('lists.json') as ListsJson;
|
|
||||||
|
|
||||||
// support giving key instead of ID
|
|
||||||
if (Object.keys(listMappings).includes(listKeyOrId)) {
|
|
||||||
listId = listMappings[listKeyOrId].readlistId;
|
|
||||||
}
|
|
||||||
|
|
||||||
const list = await getListInfo(listId);
|
|
||||||
const ids = list.bookIds;
|
|
||||||
const seriesPath = `/data/comics/[List] ${list.name}`;
|
|
||||||
|
|
||||||
const listBooks = [] as Book[];
|
|
||||||
|
|
||||||
for (let i = 0; i < ids.length; i++) {
|
|
||||||
const book = await getBookInfo(ids[i]);
|
|
||||||
|
|
||||||
listBooks[i] = book;
|
|
||||||
};
|
|
||||||
|
|
||||||
return { list, seriesPath, listBooks };
|
|
||||||
};
|
|
||||||
|
|
||||||
const main = async(): Promise<void> => {
|
|
||||||
if (process.argv[2] === 'copy') {
|
|
||||||
const { seriesPath, listBooks } = await getListBooks(process.argv[3]);
|
|
||||||
|
|
||||||
rmSync(seriesPath, { recursive: true, force: true });
|
|
||||||
mkdirSync(seriesPath, { recursive: true });
|
|
||||||
|
|
||||||
for (const book of listBooks) {
|
|
||||||
const bookPath = book.url;
|
|
||||||
const inListPath = `${seriesPath}/${basename(bookPath)}`;
|
|
||||||
|
|
||||||
console.log(`hardlinking ${basename(bookPath)}`);
|
|
||||||
linkSync(bookPath, inListPath);
|
|
||||||
}
|
|
||||||
|
|
||||||
scanLibrary();
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (process.argv[2] === 'meta') {
|
|
||||||
const { list, seriesPath, listBooks } = await getListBooks(process.argv[3]);
|
|
||||||
|
|
||||||
const seriesBooks = await getSeriesBooks(`[List] ${list.name}`, seriesPath);
|
|
||||||
|
|
||||||
for (const target of seriesBooks) {
|
|
||||||
const source = listBooks.find((b) => basename(b.url) === basename(target.url));
|
|
||||||
|
|
||||||
if (source) {
|
|
||||||
const i = listBooks.indexOf(source) + 1;
|
|
||||||
|
|
||||||
console.log(`Setting metadata for ${source.name}`);
|
|
||||||
setBookMetadata(i, source, target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (process.argv[2] === 'json') {
|
|
||||||
const { listBooks } = await getListBooks(process.argv[3]);
|
|
||||||
|
|
||||||
const output = [] as { series: string, title: string, number: number }[];
|
|
||||||
|
|
||||||
listBooks.forEach((book) => {
|
|
||||||
output.push({
|
|
||||||
series: book.seriesTitle,
|
|
||||||
title: book.metadata.title,
|
|
||||||
number: book.metadata.numberSort,
|
|
||||||
});
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(JSON.stringify(output, null, 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
else if (process.argv[2] === 'init') {
|
|
||||||
const listKey = process.argv[3];
|
|
||||||
const listMappings = readNeighborFile('lists.json') as ListsJson;
|
|
||||||
|
|
||||||
const listData = listMappings[listKey];
|
|
||||||
const cvIssueLinks = listData.issues;
|
|
||||||
|
|
||||||
const bookIds = [] as string[];
|
|
||||||
|
|
||||||
for (let i = 0; i < cvIssueLinks.length; ++i) {
|
|
||||||
const { series, title, number } = cvIssueLinks[i];
|
|
||||||
|
|
||||||
const seriesSearch = (await axios.request({
|
|
||||||
method: 'post',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: 'https://komga.nelim.org/api/v1/series/list?unpaged=true',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
condition: {
|
|
||||||
title: {
|
|
||||||
operator: 'is',
|
|
||||||
value: series,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})).data.content;
|
|
||||||
|
|
||||||
const bookSearch = [] as Book[];
|
|
||||||
|
|
||||||
for (const seriesResult of seriesSearch) {
|
|
||||||
const seriesId = seriesResult.id;
|
|
||||||
|
|
||||||
bookSearch.push(...((await axios.request({
|
|
||||||
method: 'post',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: 'https://komga.nelim.org/api/v1/books/list?unpaged=true',
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
condition: {
|
|
||||||
seriesId: {
|
|
||||||
operator: 'is',
|
|
||||||
value: seriesId,
|
|
||||||
},
|
|
||||||
title: {
|
|
||||||
operator: 'is',
|
|
||||||
value: title,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
}),
|
|
||||||
})).data.content as Book[]));
|
|
||||||
}
|
|
||||||
|
|
||||||
const matchingBooks = bookSearch.filter((b) =>
|
|
||||||
b.metadata.title === title &&
|
|
||||||
b.metadata.numberSort === number);
|
|
||||||
|
|
||||||
if (matchingBooks.length !== 1) {
|
|
||||||
console.error(matchingBooks, number);
|
|
||||||
throw new Error(`More than one issue matched the title '${title}'`);
|
|
||||||
}
|
|
||||||
|
|
||||||
bookIds[i] = matchingBooks[0].id;
|
|
||||||
}
|
|
||||||
|
|
||||||
axios.request({
|
|
||||||
method: 'patch',
|
|
||||||
maxBodyLength: Infinity,
|
|
||||||
url: `https://komga.nelim.org/api/v1/readlists/${listData.readlistId}`,
|
|
||||||
headers: {
|
|
||||||
'Content-Type': 'application/json',
|
|
||||||
'Accept': 'application/json',
|
|
||||||
'X-API-Key': API,
|
|
||||||
},
|
|
||||||
data: JSON.stringify({
|
|
||||||
bookIds,
|
|
||||||
ordered: true,
|
|
||||||
// name: 'string',
|
|
||||||
// summary: 'string',
|
|
||||||
}),
|
|
||||||
});
|
|
||||||
|
|
||||||
console.log(`Updated ${listKey}.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
else {
|
|
||||||
console.error('Arguments not recognized.');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
main();
|
|
|
@ -1,146 +0,0 @@
|
||||||
export interface ListJson {
|
|
||||||
readlistId: string
|
|
||||||
issues: {
|
|
||||||
series: string
|
|
||||||
title: string
|
|
||||||
number: number
|
|
||||||
}[]
|
|
||||||
}
|
|
||||||
|
|
||||||
export type ListsJson = Record<string, ListJson>;
|
|
||||||
|
|
||||||
export interface Media {
|
|
||||||
status: string
|
|
||||||
mediaType: string
|
|
||||||
pagesCount: number
|
|
||||||
comment: string
|
|
||||||
epubDivinaCompatible: boolean
|
|
||||||
epubIsKepub: boolean
|
|
||||||
mediaProfile: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Author {
|
|
||||||
name: string
|
|
||||||
role: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Link {
|
|
||||||
label: string
|
|
||||||
url: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ShortBookMetadata {
|
|
||||||
authors: Author[]
|
|
||||||
tags: unknown[]
|
|
||||||
releaseDate: string
|
|
||||||
summary: string
|
|
||||||
summaryNumber: string
|
|
||||||
created: string
|
|
||||||
lastModified: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface BookMetadata {
|
|
||||||
title: string
|
|
||||||
titleLock: boolean
|
|
||||||
summary: string
|
|
||||||
summaryLock: boolean
|
|
||||||
number: string
|
|
||||||
numberLock: boolean
|
|
||||||
numberSort: number
|
|
||||||
numberSortLock: boolean
|
|
||||||
releaseDate: string
|
|
||||||
releaseDateLock: boolean
|
|
||||||
authors: Author[]
|
|
||||||
authorsLock: boolean
|
|
||||||
tags: unknown[]
|
|
||||||
tagsLock: boolean
|
|
||||||
isbn: string
|
|
||||||
isbnLock: boolean
|
|
||||||
links: Link[]
|
|
||||||
linksLock: boolean
|
|
||||||
created: string
|
|
||||||
lastModified: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Book {
|
|
||||||
id: string
|
|
||||||
seriesId: string
|
|
||||||
seriesTitle: string
|
|
||||||
libraryId: string
|
|
||||||
name: string
|
|
||||||
url: string
|
|
||||||
number: number
|
|
||||||
created: string
|
|
||||||
lastModified: string
|
|
||||||
fileLastModified: string
|
|
||||||
sizeBytes: number
|
|
||||||
size: string
|
|
||||||
media: Media
|
|
||||||
metadata: BookMetadata
|
|
||||||
readProgress: null | unknown
|
|
||||||
deleted: boolean
|
|
||||||
fileHash: string
|
|
||||||
oneshot: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface SeriesMetadata {
|
|
||||||
status: string
|
|
||||||
statusLock: boolean
|
|
||||||
title: string
|
|
||||||
titleLock: boolean
|
|
||||||
titleSort: string
|
|
||||||
titleSortLock: boolean
|
|
||||||
summary: string
|
|
||||||
summaryLock: boolean
|
|
||||||
readingDirection: string
|
|
||||||
readingDirectionLock: boolean
|
|
||||||
publisher: string
|
|
||||||
publisherLock: boolean
|
|
||||||
ageRating: null | string
|
|
||||||
ageRatingLock: boolean
|
|
||||||
language: string
|
|
||||||
languageLock: boolean
|
|
||||||
genres: string[]
|
|
||||||
genresLock: boolean
|
|
||||||
tags: unknown[]
|
|
||||||
tagsLock: boolean
|
|
||||||
totalBookCount: null | number
|
|
||||||
totalBookCountLock: boolean
|
|
||||||
sharingLabels: unknown[]
|
|
||||||
sharingLabelsLock: boolean
|
|
||||||
links: Link[]
|
|
||||||
linksLock: boolean
|
|
||||||
alternateTitles: string[]
|
|
||||||
alternateTitlesLock: boolean
|
|
||||||
created: string
|
|
||||||
lastModified: string
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface Series {
|
|
||||||
id: string
|
|
||||||
libraryId: string
|
|
||||||
name: string
|
|
||||||
url: string
|
|
||||||
created: string
|
|
||||||
lastModified: string
|
|
||||||
fileLastModified: string
|
|
||||||
booksCount: number
|
|
||||||
booksReadCount: number
|
|
||||||
booksUnreadCount: number
|
|
||||||
booksInProgressCount: number
|
|
||||||
metadata: SeriesMetadata
|
|
||||||
booksMetadata: ShortBookMetadata
|
|
||||||
deleted: boolean
|
|
||||||
oneshot: boolean
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface ReadList {
|
|
||||||
id: string
|
|
||||||
name: string
|
|
||||||
summary: string
|
|
||||||
ordered: boolean
|
|
||||||
bookIds: string[]
|
|
||||||
createdDate: string
|
|
||||||
lastModifiedDate: string
|
|
||||||
filtered: boolean
|
|
||||||
}
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "../config/tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
use flake $FLAKE#node
|
|
||||||
(cd ../config; npm ci)
|
|
||||||
npm ci
|
|
|
@ -1,18 +0,0 @@
|
||||||
{
|
|
||||||
buildApp,
|
|
||||||
nodejs_latest,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
buildApp {
|
|
||||||
src = ./.;
|
|
||||||
npmDepsHash = "sha256-ataURmJVvNIcJ+NSu2CCsVGbtuVn6gQa9ZN38LLF5V4=";
|
|
||||||
|
|
||||||
runtimeInputs = [
|
|
||||||
nodejs_latest
|
|
||||||
];
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Checks if a list of mods have a version available for a specific Minecraft
|
|
||||||
version and a specific loader.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from 'eslint-conf';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
1536
apps/mc-mods/package-lock.json
generated
1536
apps/mc-mods/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"name": "mc-mods",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bin": "out/bin/app.cjs",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "22.15.29",
|
|
||||||
"esbuild": "0.25.5",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"pkg-types": "2.1.0",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint-conf": "file:../config"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,147 +0,0 @@
|
||||||
import { createWriteStream, mkdirSync, rmSync } from 'fs';
|
|
||||||
import { Readable } from 'stream';
|
|
||||||
|
|
||||||
interface Hashes {
|
|
||||||
sha1: string
|
|
||||||
sha512: string
|
|
||||||
}
|
|
||||||
interface File {
|
|
||||||
hashes: Hashes
|
|
||||||
url: string
|
|
||||||
filename: string
|
|
||||||
primary: boolean
|
|
||||||
size: number
|
|
||||||
file_type: string
|
|
||||||
}
|
|
||||||
interface Dependency {
|
|
||||||
version_id: string
|
|
||||||
project_id: string
|
|
||||||
file_name: string
|
|
||||||
dependency_type: string
|
|
||||||
}
|
|
||||||
interface ModVersion {
|
|
||||||
game_versions: string[]
|
|
||||||
loaders: string[]
|
|
||||||
id: string
|
|
||||||
project_id: string
|
|
||||||
author_id: string
|
|
||||||
featured: boolean
|
|
||||||
name: string
|
|
||||||
version_number: string
|
|
||||||
changelog: string
|
|
||||||
changelog_url: string
|
|
||||||
date_published: string
|
|
||||||
downloads: number
|
|
||||||
version_type: string
|
|
||||||
status: string
|
|
||||||
files: File[]
|
|
||||||
dependencies: Dependency[]
|
|
||||||
}
|
|
||||||
|
|
||||||
const LOADER = 'fabric';
|
|
||||||
|
|
||||||
const game_version = process.argv[2] ?? '';
|
|
||||||
const action = process.argv[3] ?? 'check';
|
|
||||||
|
|
||||||
const getVersions = async(slug: string): Promise<ModVersion[]> => {
|
|
||||||
const res = await fetch(`https://api.modrinth.com/v2/project/${slug}/version`);
|
|
||||||
|
|
||||||
return res.ok ?
|
|
||||||
await res.json() as ModVersion[] :
|
|
||||||
[];
|
|
||||||
};
|
|
||||||
|
|
||||||
const checkModCompat = async(slug: string): Promise<ModVersion | null> => {
|
|
||||||
const versions = await getVersions(slug);
|
|
||||||
|
|
||||||
const matching = versions.filter((ver) =>
|
|
||||||
ver.game_versions.includes(game_version) &&
|
|
||||||
ver.loaders.includes(LOADER));
|
|
||||||
|
|
||||||
if (matching.length === 0) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
const timeSorted = matching.sort((a, b) => {
|
|
||||||
const dateA = new Date(a.date_published);
|
|
||||||
const dateB = new Date(b.date_published);
|
|
||||||
|
|
||||||
return dateB.getTime() - dateA.getTime();
|
|
||||||
});
|
|
||||||
|
|
||||||
return timeSorted.some((v) => v.version_type === 'release') ?
|
|
||||||
timeSorted.filter((v) => v.version_type === 'release')[0] :
|
|
||||||
timeSorted[0];
|
|
||||||
};
|
|
||||||
|
|
||||||
const getDownloadUrls = (version: ModVersion): string[] => version.files.map((file) => file.url);
|
|
||||||
|
|
||||||
const showModDownloadUrls = async(modName: string): Promise<boolean> => {
|
|
||||||
const ver = await checkModCompat(modName);
|
|
||||||
|
|
||||||
if (ver) {
|
|
||||||
const urls = getDownloadUrls(ver);
|
|
||||||
|
|
||||||
console.log(`\n${modName}:`, urls);
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
const download = async(url: string, path: string) => Readable
|
|
||||||
.fromWeb((await fetch(url)).body!).pipe(createWriteStream(path));
|
|
||||||
|
|
||||||
const main = () => {
|
|
||||||
const mods = [
|
|
||||||
'badpackets',
|
|
||||||
'c2me-fabric',
|
|
||||||
'cloth-config',
|
|
||||||
'clumps',
|
|
||||||
'fabric-api',
|
|
||||||
'ferrite-core',
|
|
||||||
'leaves-be-gone',
|
|
||||||
'lithium',
|
|
||||||
'modernfix',
|
|
||||||
'no-chat-reports',
|
|
||||||
'noisium',
|
|
||||||
'vmp-fabric',
|
|
||||||
'wthit',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (action === 'check') {
|
|
||||||
mods.forEach(async(modName) => {
|
|
||||||
if (!(await showModDownloadUrls(modName))) {
|
|
||||||
console.error(`No matching releases of ${modName} were found for ${game_version}`);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
else if (action === 'download') {
|
|
||||||
rmSync('./out', { force: true, recursive: true });
|
|
||||||
mkdirSync('./out');
|
|
||||||
|
|
||||||
mods.forEach(async(modName) => {
|
|
||||||
const ver = await checkModCompat(modName);
|
|
||||||
|
|
||||||
if (ver === null) {
|
|
||||||
console.error(`No matching releases of ${modName} were found for ${game_version}`);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const fileName =
|
|
||||||
`${modName}-${ver.version_number}.jar`;
|
|
||||||
|
|
||||||
console.log(`Downloading ${fileName}`);
|
|
||||||
|
|
||||||
await download(
|
|
||||||
ver.files[0].url,
|
|
||||||
`./out/${fileName}`,
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
main();
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "../config/tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,16 +0,0 @@
|
||||||
{inputs, ...}: (final: prev: {
|
|
||||||
appsPackages = let
|
|
||||||
inherit (final.lib) listToAttrs nameValuePair;
|
|
||||||
|
|
||||||
buildApp = attrs: (final.callPackage ./buildApp.nix ({} // inputs // attrs));
|
|
||||||
callPackage = file: final.callPackage file ({inherit buildApp;} // inputs);
|
|
||||||
in
|
|
||||||
listToAttrs (map (x: nameValuePair x (callPackage ./${x})) [
|
|
||||||
"extract-subs"
|
|
||||||
"gen-docs"
|
|
||||||
"list2series"
|
|
||||||
"mc-mods"
|
|
||||||
"pin-inputs"
|
|
||||||
"update-sources"
|
|
||||||
]);
|
|
||||||
})
|
|
|
@ -1,3 +0,0 @@
|
||||||
use flake $FLAKE#node
|
|
||||||
(cd ../config; npm ci)
|
|
||||||
npm ci
|
|
|
@ -1,11 +0,0 @@
|
||||||
{buildApp, ...}:
|
|
||||||
buildApp {
|
|
||||||
src = ./.;
|
|
||||||
npmDepsHash = "sha256-Z9xyq3T66PXg982SAMBtAZdfBo6e3gZ30N8AcgUZ64k=";
|
|
||||||
|
|
||||||
runtimeInputs = [];
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Takes a list of inputs to pin to their current rev in `flake.lock`.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from 'eslint-conf';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
1536
apps/pin-inputs/package-lock.json
generated
1536
apps/pin-inputs/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"name": "pin-inputs",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bin": "out/bin/app.cjs",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "22.15.29",
|
|
||||||
"esbuild": "0.25.5",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"pkg-types": "2.1.0",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint-conf": "file:../config"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,62 +0,0 @@
|
||||||
import { readFileSync, writeFileSync } from 'fs';
|
|
||||||
|
|
||||||
export const replaceInFile = (replace: RegExp, replacement: string, file: string) => {
|
|
||||||
const fileContents = readFileSync(file);
|
|
||||||
|
|
||||||
const replaced = fileContents.toString().replace(replace, replacement);
|
|
||||||
|
|
||||||
writeFileSync(file, replaced);
|
|
||||||
};
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
if (!FLAKE) {
|
|
||||||
console.error('Environment variable FLAKE not found');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const FLAKE_LOCK = JSON.parse(readFileSync(`${FLAKE}/flake.lock`, 'utf8')).nodes;
|
|
||||||
const INPUT_REVS = new Map<string, string>();
|
|
||||||
|
|
||||||
Object.entries(FLAKE_LOCK).forEach(([key, val]) => {
|
|
||||||
if (key !== 'root') {
|
|
||||||
// eslint-disable-next-line
|
|
||||||
INPUT_REVS.set(key, (val as any).locked.rev);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
const INPUTS = process.argv.slice(2);
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Gets the commit hash of the specified input in this flake.
|
|
||||||
*
|
|
||||||
* @param input the name of the input
|
|
||||||
* @returns the commit hash
|
|
||||||
*/
|
|
||||||
const getCurrentRev = (input: string): string => {
|
|
||||||
if (!INPUT_REVS.has(input)) {
|
|
||||||
throw new Error(`Input ${input} could not be found.`);
|
|
||||||
}
|
|
||||||
|
|
||||||
return INPUT_REVS.get(input) as string;
|
|
||||||
};
|
|
||||||
|
|
||||||
INPUTS.forEach((input) => {
|
|
||||||
try {
|
|
||||||
const inputsFile = `${FLAKE}/inputs/default.nix`;
|
|
||||||
const rev = getCurrentRev(input);
|
|
||||||
|
|
||||||
const msg = ['FIX', 'ME'].join('');
|
|
||||||
|
|
||||||
replaceInFile(
|
|
||||||
new RegExp(`(\\n[ ]*)${input} =.*\\n.*\\n.*`),
|
|
||||||
`$&\n$1 # ${msg}: $1 rev = "${rev}";`,
|
|
||||||
inputsFile,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.error((e as Error).message);
|
|
||||||
}
|
|
||||||
});
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "../config/tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
use flake $FLAKE#node
|
|
||||||
(cd ../config; npm ci)
|
|
||||||
npm ci
|
|
|
@ -1,36 +0,0 @@
|
||||||
{
|
|
||||||
buildApp,
|
|
||||||
callPackage,
|
|
||||||
curl,
|
|
||||||
findutils,
|
|
||||||
go,
|
|
||||||
jq,
|
|
||||||
just,
|
|
||||||
nix-update,
|
|
||||||
nodejs_latest,
|
|
||||||
prefetch-npm-deps,
|
|
||||||
...
|
|
||||||
}:
|
|
||||||
buildApp {
|
|
||||||
src = ./.;
|
|
||||||
npmDepsHash = "sha256-aV6o54XWtkkYFEecA7A6kWnJRCrSJelk36DYyNvXdWI=";
|
|
||||||
|
|
||||||
runtimeInputs = [
|
|
||||||
curl
|
|
||||||
findutils
|
|
||||||
go
|
|
||||||
jq
|
|
||||||
just
|
|
||||||
nix-update
|
|
||||||
nodejs_latest
|
|
||||||
prefetch-npm-deps
|
|
||||||
# We want to use the one from my config with authfile
|
|
||||||
# (callPackage ../../modules/docker/updateImage.nix {})
|
|
||||||
(callPackage ../../configurations/homie/modules/home-assistant/netdaemon/update.nix {})
|
|
||||||
];
|
|
||||||
|
|
||||||
meta.description = ''
|
|
||||||
Updates all derivation sources in this repository and
|
|
||||||
generates a commit message for the changes made.
|
|
||||||
'';
|
|
||||||
}
|
|
|
@ -1,3 +0,0 @@
|
||||||
import eslintConf from 'eslint-conf';
|
|
||||||
|
|
||||||
export default eslintConf;
|
|
1536
apps/update-sources/package-lock.json
generated
1536
apps/update-sources/package-lock.json
generated
File diff suppressed because it is too large
Load diff
|
@ -1,20 +0,0 @@
|
||||||
{
|
|
||||||
"name": "update-sources",
|
|
||||||
"version": "0.0.0",
|
|
||||||
"bin": "out/bin/app.cjs",
|
|
||||||
"type": "module",
|
|
||||||
"scripts": {
|
|
||||||
"build": "node_ver=$(node -v); esbuild src/app.ts --bundle --platform=node --target=\"node${node_ver:1:2}\" --outfile=out/bin/app.cjs"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"@types/node": "22.15.29",
|
|
||||||
"esbuild": "0.25.5",
|
|
||||||
"eslint": "9.28.0",
|
|
||||||
"jiti": "2.4.2",
|
|
||||||
"pkg-types": "2.1.0",
|
|
||||||
"typescript": "5.8.3"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
|
||||||
"eslint-conf": "file:../config"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -1,209 +0,0 @@
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { writeFileSync } from 'node:fs';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
import { parseArgs } from './lib';
|
|
||||||
|
|
||||||
import updateCaddyPlugins from './caddy';
|
|
||||||
import updateDocker from './docker';
|
|
||||||
import updateFirefoxAddons from '././firefox';
|
|
||||||
import updateFlakeInputs from './flake';
|
|
||||||
import updateNetDaemon from './netdaemon';
|
|
||||||
import runNixUpdate from './nix-update';
|
|
||||||
import updateNodeModules from './node-modules';
|
|
||||||
import updateVuetorrent from './vuetorrent';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
if (!FLAKE) {
|
|
||||||
console.error('Environment variable FLAKE was not found.\n');
|
|
||||||
process.exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
const args = parseArgs();
|
|
||||||
|
|
||||||
const main = async() => {
|
|
||||||
if (args['custom-sidebar']) {
|
|
||||||
console.log(
|
|
||||||
runNixUpdate('scopedPackages', 'lovelace-components', 'custom-sidebar') ?? 'No updates',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['caddy'] || args['caddy-plugins']) {
|
|
||||||
console.log(updateCaddyPlugins() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['docker']) {
|
|
||||||
console.log(updateDocker() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['firefox']) {
|
|
||||||
console.log(updateFirefoxAddons() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['homepage']) {
|
|
||||||
console.log(runNixUpdate('homepage') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['flake'] || args['inputs']) {
|
|
||||||
console.log(updateFlakeInputs() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['jmusicbot']) {
|
|
||||||
console.log(runNixUpdate('jmusicbot') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['material-rounded-theme']) {
|
|
||||||
console.log(
|
|
||||||
runNixUpdate('scopedPackages', 'lovelace-components', 'material-rounded-theme') ??
|
|
||||||
'No updates',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['netdaemon']) {
|
|
||||||
console.log(updateNetDaemon() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['node'] || args['node_modules']) {
|
|
||||||
console.log((await updateNodeModules()) ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['pam-fprint-grosshack']) {
|
|
||||||
console.log(runNixUpdate('pam-fprint-grosshack') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['protonhax']) {
|
|
||||||
console.log(runNixUpdate('protonhax') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['some-sass-language-server']) {
|
|
||||||
console.log(runNixUpdate('some-sass-language-server') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['trash'] || args['trash-d']) {
|
|
||||||
console.log(runNixUpdate('trash-d') ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['vuetorrent']) {
|
|
||||||
console.log(updateVuetorrent() ?? 'No updates');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['a'] || args['all']) {
|
|
||||||
// Update this first because of nix run cmd
|
|
||||||
const firefoxOutput = updateFirefoxAddons();
|
|
||||||
|
|
||||||
console.log(firefoxOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const flakeOutput = updateFlakeInputs();
|
|
||||||
|
|
||||||
console.log(flakeOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const dockerOutput = updateDocker();
|
|
||||||
|
|
||||||
console.log(dockerOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const netdaemonOutput = updateNetDaemon();
|
|
||||||
|
|
||||||
console.log(netdaemonOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const nodeModulesOutput = await updateNodeModules();
|
|
||||||
|
|
||||||
console.log(nodeModulesOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const vuetorrentOutput = updateVuetorrent();
|
|
||||||
|
|
||||||
console.log(vuetorrentOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
const caddyPluginsOutput = updateCaddyPlugins();
|
|
||||||
|
|
||||||
console.log(caddyPluginsOutput ?? 'No updates');
|
|
||||||
|
|
||||||
|
|
||||||
// nix-update executions
|
|
||||||
const nixUpdateOutputs: string[] = [];
|
|
||||||
|
|
||||||
const updatePackage = (
|
|
||||||
attr: string,
|
|
||||||
scope?: string,
|
|
||||||
scopeAttr?: string,
|
|
||||||
): void => {
|
|
||||||
const execution = runNixUpdate(attr, scope, scopeAttr);
|
|
||||||
|
|
||||||
if (execution) {
|
|
||||||
nixUpdateOutputs.push(execution);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
updatePackage('homepage');
|
|
||||||
updatePackage('jmusicbot');
|
|
||||||
updatePackage('pam-fprint-grosshack');
|
|
||||||
updatePackage('protonhax');
|
|
||||||
updatePackage('some-sass-language-server');
|
|
||||||
updatePackage('trash-d');
|
|
||||||
updatePackage('scopedPackages', 'lovelace-components', 'custom-sidebar');
|
|
||||||
updatePackage('scopedPackages', 'lovelace-components', 'material-rounded-theme');
|
|
||||||
|
|
||||||
|
|
||||||
spawnSync(`alejandra -q ${FLAKE}`, [], { shell: true });
|
|
||||||
|
|
||||||
spawnSync('nixFastBuild', [], {
|
|
||||||
shell: true,
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
|
|
||||||
const indentOutput = (output: string): string => {
|
|
||||||
return ` ${output.replace(/\n*$/g, '').split('\n').join('\n ')}`;
|
|
||||||
};
|
|
||||||
|
|
||||||
const output = [
|
|
||||||
'chore: update sources',
|
|
||||||
];
|
|
||||||
|
|
||||||
if (flakeOutput) {
|
|
||||||
output.push(`Flake Inputs:\n${indentOutput(flakeOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (dockerOutput) {
|
|
||||||
output.push(`Docker Images:\n${indentOutput(dockerOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (firefoxOutput) {
|
|
||||||
output.push(`Firefox Addons:\n${indentOutput(firefoxOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (nodeModulesOutput) {
|
|
||||||
output.push(`Node modules:\n${indentOutput(nodeModulesOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (vuetorrentOutput) {
|
|
||||||
output.push(`qBittorrent Sources:\n${indentOutput(vuetorrentOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (caddyPluginsOutput) {
|
|
||||||
output.push(`Caddy Plugins:\n${indentOutput(caddyPluginsOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (netdaemonOutput) {
|
|
||||||
output.push(`NetDaemon:\n${indentOutput(netdaemonOutput)}\n`);
|
|
||||||
}
|
|
||||||
if (nixUpdateOutputs.length > 0) {
|
|
||||||
output.push(`nix-update executions:\n${indentOutput(nixUpdateOutputs.join('\n'))}\n`);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (args['f']) {
|
|
||||||
console.log(styleText(['magenta'], `\n\nWriting commit message to ${args['f']}\n`));
|
|
||||||
writeFileSync(args['f'], output.join('\n\n'));
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.log(styleText(['magenta'], '\n\nCommit message:\n'));
|
|
||||||
console.log(output.join('\n\n'));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
spawnSync(`alejandra -q ${FLAKE}`, [], { shell: true });
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
main();
|
|
|
@ -1,92 +0,0 @@
|
||||||
import { writeFileSync } from 'node:fs';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
|
|
||||||
import { replaceInFile } from './lib';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
/* Types */
|
|
||||||
interface Plugin {
|
|
||||||
url: string
|
|
||||||
version: string
|
|
||||||
type: 'version' | 'git'
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
const genPluginsText = (
|
|
||||||
plugins: Record<string, Plugin>,
|
|
||||||
) => `{
|
|
||||||
plugins = {
|
|
||||||
${Object.entries(plugins)
|
|
||||||
.map(([key, value]) => `
|
|
||||||
${key} = {
|
|
||||||
url = "${value.url}";
|
|
||||||
version = "${value.version}";
|
|
||||||
type = "${value.type}";
|
|
||||||
};
|
|
||||||
`)
|
|
||||||
.join('')}
|
|
||||||
};
|
|
||||||
|
|
||||||
hash = "";
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating caddy plugins:\n'));
|
|
||||||
|
|
||||||
const updates: string[] = [];
|
|
||||||
const dir = `${FLAKE}/configurations/cluster/modules/caddy`;
|
|
||||||
|
|
||||||
// Setup workspace
|
|
||||||
spawnSync(
|
|
||||||
[
|
|
||||||
'rm -rf /tmp/update-caddy',
|
|
||||||
'mkdir -p /tmp/update-caddy',
|
|
||||||
'cd /tmp/update-caddy || exit 1',
|
|
||||||
'go mod init temp',
|
|
||||||
].join('; '),
|
|
||||||
[],
|
|
||||||
{ shell: true, cwd: '/tmp' },
|
|
||||||
);
|
|
||||||
|
|
||||||
const plugins = JSON.parse(spawnSync(
|
|
||||||
['nix', 'eval', '-f', `${dir}/plugins.nix`, '--json'].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString()).plugins as Record<string, Plugin>;
|
|
||||||
|
|
||||||
// Get most recent versions of plugins
|
|
||||||
Object.entries(plugins).forEach(([key, value]) => {
|
|
||||||
const NEW_VERSION = spawnSync([
|
|
||||||
'go mod init temp > /dev/null',
|
|
||||||
`go get ${value.url}${value.type === 'git' ? '@HEAD' : ''} > /dev/null`,
|
|
||||||
`grep '${value.url}' go.mod`,
|
|
||||||
].join('; '), [], { shell: true, cwd: '/tmp/update-caddy' })
|
|
||||||
.stdout
|
|
||||||
.toString()
|
|
||||||
.trim()
|
|
||||||
.replace(' // indirect', '')
|
|
||||||
.split(' ')[1];
|
|
||||||
|
|
||||||
if (plugins[key].version !== NEW_VERSION) {
|
|
||||||
updates.push(`${key}: ${plugins[key].version} -> ${NEW_VERSION}`);
|
|
||||||
plugins[key].version = NEW_VERSION;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
writeFileSync(`${dir}/plugins.nix`, genPluginsText(plugins));
|
|
||||||
|
|
||||||
// Get new hash
|
|
||||||
const caddyPkgAttr = 'nixosConfigurations.thingone.config.services.caddy.package';
|
|
||||||
|
|
||||||
const NEW_HASH = spawnSync(
|
|
||||||
`nix build "$FLAKE#${caddyPkgAttr}" |& sed -n 's/.*got: *//p'`,
|
|
||||||
[],
|
|
||||||
{ shell: true },
|
|
||||||
).stdout.toString().trim();
|
|
||||||
|
|
||||||
replaceInFile(/hash = ".*";/, `hash = "${NEW_HASH}";`, `${dir}/plugins.nix`);
|
|
||||||
|
|
||||||
return updates.length > 0 ? updates.join('\n') : null;
|
|
||||||
};
|
|
|
@ -1,57 +0,0 @@
|
||||||
import { readdirSync } from 'node:fs';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
const updateImages = (imagePath: string): string | undefined => {
|
|
||||||
console.log(`Updating ${imagePath.split('/').at(-1)} images`);
|
|
||||||
|
|
||||||
const out = spawnSync(`updateImages ${imagePath}`, [], { shell: true }).stdout.toString();
|
|
||||||
|
|
||||||
if (out.length > 1) {
|
|
||||||
return out;
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating docker images:\n'));
|
|
||||||
|
|
||||||
const updates: string[] = [];
|
|
||||||
|
|
||||||
const jdownloaderUpdates = updateImages(`${FLAKE}/configurations/nos/modules/comics/jdownloader2`);
|
|
||||||
|
|
||||||
if (jdownloaderUpdates) {
|
|
||||||
updates.push(jdownloaderUpdates);
|
|
||||||
}
|
|
||||||
|
|
||||||
const jellfyinUpdates = updateImages(`${FLAKE}/configurations/nos/modules/jellyfin`);
|
|
||||||
|
|
||||||
if (jellfyinUpdates) {
|
|
||||||
updates.push(jellfyinUpdates);
|
|
||||||
}
|
|
||||||
|
|
||||||
const hassUpdates = updateImages(`${FLAKE}/configurations/homie/modules/home-assistant/netdaemon`);
|
|
||||||
|
|
||||||
if (hassUpdates) {
|
|
||||||
updates.push(hassUpdates);
|
|
||||||
}
|
|
||||||
|
|
||||||
const DIR = `${FLAKE}/configurations/nos/modules/docker`;
|
|
||||||
|
|
||||||
readdirSync(DIR, { withFileTypes: true, recursive: true }).forEach((path) => {
|
|
||||||
if (path.name === 'compose.nix') {
|
|
||||||
const composeUpdates = updateImages(path.parentPath);
|
|
||||||
|
|
||||||
if (composeUpdates) {
|
|
||||||
updates.push(composeUpdates);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return updates.length > 0 ?
|
|
||||||
updates.join('') :
|
|
||||||
null;
|
|
||||||
};
|
|
|
@ -1,63 +0,0 @@
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { readFileSync } from 'node:fs';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating firefox addons using mozilla-addons-to-nix:\n'));
|
|
||||||
|
|
||||||
const DIR = `${FLAKE}/scopedPackages/firefox-addons`;
|
|
||||||
const GENERATED_FILE = `${DIR}/generated-firefox-addons.nix`;
|
|
||||||
const SLUGS = `${DIR}/addons.json`;
|
|
||||||
|
|
||||||
const nameMap = Object.fromEntries([...JSON.parse(readFileSync(SLUGS, 'utf-8'))]
|
|
||||||
.map((addon) => [addon.slug, addon.pname || addon.slug]));
|
|
||||||
|
|
||||||
const nixExpr = `'
|
|
||||||
x: let
|
|
||||||
inherit (builtins) attrValues filter hasAttr isAttrs map;
|
|
||||||
in
|
|
||||||
map (d: d.name) (filter (y:
|
|
||||||
isAttrs y &&
|
|
||||||
hasAttr "type" y &&
|
|
||||||
y.type == "derivation") (attrValues x))
|
|
||||||
'`;
|
|
||||||
|
|
||||||
const OLD_VERS = Object.fromEntries([...JSON.parse(spawnSync([
|
|
||||||
'nix',
|
|
||||||
'eval',
|
|
||||||
'.#scopedPackages.x86_64-linux.firefoxAddons',
|
|
||||||
'--apply',
|
|
||||||
nixExpr,
|
|
||||||
'--json',
|
|
||||||
].join(' '), [], { shell: true }).stdout.toString())]
|
|
||||||
.map((p) => {
|
|
||||||
const pname = p.replace(/-[0-9].*$/, '');
|
|
||||||
|
|
||||||
return [pname, p.replace(`${pname}-`, '')];
|
|
||||||
})
|
|
||||||
.filter((pinfo) => pinfo[0] !== 'frankerfacez'));
|
|
||||||
|
|
||||||
const NEW_VERS = Object.fromEntries(spawnSync([
|
|
||||||
'nix', 'run', 'sourcehut:~rycee/mozilla-addons-to-nix', SLUGS, GENERATED_FILE,
|
|
||||||
].join(' '), [], { shell: true }).stdout
|
|
||||||
.toString()
|
|
||||||
.split('\n')
|
|
||||||
.map((p) => {
|
|
||||||
const pinfo = p.replace('Fetched ', '').split(' ');
|
|
||||||
|
|
||||||
return [nameMap[pinfo[0]], pinfo[2]];
|
|
||||||
}));
|
|
||||||
|
|
||||||
const changelogs = Object.keys(OLD_VERS)
|
|
||||||
.sort()
|
|
||||||
.filter((pname) => OLD_VERS[pname] !== NEW_VERS[pname])
|
|
||||||
.map((pname) => `${pname}: ${OLD_VERS[pname]} -> ${NEW_VERS[pname]}`);
|
|
||||||
|
|
||||||
return changelogs.length > 0 ?
|
|
||||||
changelogs.join('\n') :
|
|
||||||
null;
|
|
||||||
};
|
|
|
@ -1,59 +0,0 @@
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating flake inputs:\n'));
|
|
||||||
|
|
||||||
const output: string = spawnSync(
|
|
||||||
`git restore flake.lock &> /dev/null; nix flake update --flake ${FLAKE}` +
|
|
||||||
' |& grep -v "warning: updating lock file" |& grep -v "unpacking"',
|
|
||||||
[],
|
|
||||||
{ shell: true },
|
|
||||||
).stdout.toString();
|
|
||||||
|
|
||||||
const inputsUpdates: string[] = output
|
|
||||||
// Get an array of each update / change
|
|
||||||
.split('\n•')
|
|
||||||
// Filter out some inputs
|
|
||||||
.filter((input) => ![
|
|
||||||
'systems',
|
|
||||||
'flake-compat',
|
|
||||||
'flake-utils',
|
|
||||||
'flake-parts',
|
|
||||||
'treefmt-nix',
|
|
||||||
'lib-aggregate',
|
|
||||||
'lib-aggregate/nixpkgs-lib',
|
|
||||||
'nix-gaming/umu',
|
|
||||||
'nix-github-actions',
|
|
||||||
'pre-commit-hooks',
|
|
||||||
].some((inputName) => input.startsWith(` Updated input '${inputName}'`)));
|
|
||||||
|
|
||||||
const formattedOutput: string = inputsUpdates
|
|
||||||
// Add an extra blank line between inputs
|
|
||||||
.join('\n\n•')
|
|
||||||
// Help readability of git revs
|
|
||||||
.split('\n')
|
|
||||||
.map((l) => l
|
|
||||||
.replace(
|
|
||||||
/\/(.{40})\?narHash=sha256[^']*(.*)/,
|
|
||||||
(_, backref1, backref2) => `${backref2} rev: ${backref1}`,
|
|
||||||
)
|
|
||||||
.replace(
|
|
||||||
/\?ref.*&rev=(.{40})[^'&]*(.*)/,
|
|
||||||
(_, backref1, backref2) => `${backref2} rev: ${backref1}`,
|
|
||||||
))
|
|
||||||
.join('\n');
|
|
||||||
|
|
||||||
// make sure we cleanup 'follows' statements
|
|
||||||
spawnSync('just genflake', [], {
|
|
||||||
cwd: FLAKE, shell: true, stdio: 'inherit',
|
|
||||||
});
|
|
||||||
|
|
||||||
return inputsUpdates.length > 0 ?
|
|
||||||
formattedOutput :
|
|
||||||
null;
|
|
||||||
};
|
|
|
@ -1,49 +0,0 @@
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { readFileSync, writeFileSync } from 'node:fs';
|
|
||||||
|
|
||||||
/* Types */
|
|
||||||
interface Args {
|
|
||||||
f: string | undefined
|
|
||||||
[name: string]: unknown
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
export const parseArgs = (): Args => {
|
|
||||||
const args = {} as Args;
|
|
||||||
let lastFlag: string | null = null;
|
|
||||||
|
|
||||||
for (let i = 2; i < process.argv.length; ++i) {
|
|
||||||
const arg = process.argv[i];
|
|
||||||
|
|
||||||
if (arg.toString().startsWith('-')) {
|
|
||||||
lastFlag = arg.toString().replace(/^-{1,2}/, '');
|
|
||||||
args[lastFlag] = true;
|
|
||||||
}
|
|
||||||
else if (lastFlag) {
|
|
||||||
args[lastFlag] = arg;
|
|
||||||
lastFlag = null;
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
console.error(`Could not parse args: ${arg.toString()}`);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return args;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const parseFetchurl = (url: string): string => JSON.parse(spawnSync(
|
|
||||||
['nix', 'store', 'prefetch-file', '--refresh', '--json',
|
|
||||||
'--hash-type', 'sha256', url, '--name', '"escaped"'].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString()).hash;
|
|
||||||
|
|
||||||
export const replaceInFile = (replace: RegExp, replacement: string, file: string): void => {
|
|
||||||
const fileContents = readFileSync(file);
|
|
||||||
|
|
||||||
const replaced = fileContents.toString().replace(replace, replacement);
|
|
||||||
|
|
||||||
writeFileSync(file, replaced);
|
|
||||||
};
|
|
||||||
|
|
||||||
export const npmRun = (args: string[], workspaceDir: string): string => spawnSync(
|
|
||||||
'npm', args, { cwd: workspaceDir },
|
|
||||||
).stdout.toString();
|
|
|
@ -1,32 +0,0 @@
|
||||||
import { readFileSync, writeFileSync } from 'node:fs';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating NetDaemon:\n'));
|
|
||||||
|
|
||||||
const FOLDER = `${FLAKE}/configurations/homie/modules/home-assistant/netdaemon`;
|
|
||||||
|
|
||||||
const OLD_VERSION = readFileSync(`${FOLDER}/.version`).toString().replace('\n', '');
|
|
||||||
|
|
||||||
const VERSION = JSON.parse(spawnSync([
|
|
||||||
'curl', '-s', 'https://api.github.com/repos/net-daemon/netdaemon/releases/latest',
|
|
||||||
].join(' '), [], { shell: true }).stdout.toString()).tag_name.replace('v', '');
|
|
||||||
|
|
||||||
if (OLD_VERSION !== VERSION) {
|
|
||||||
writeFileSync(`${FOLDER}/.version`, `${VERSION}\n`);
|
|
||||||
|
|
||||||
spawnSync('bumpNetdaemonDeps', [], {
|
|
||||||
cwd: FOLDER,
|
|
||||||
stdio: 'inherit',
|
|
||||||
});
|
|
||||||
|
|
||||||
return `NetDaemon: ${OLD_VERSION} -> ${VERSION}\n`;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
};
|
|
|
@ -1,31 +0,0 @@
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
const getAttrVersion = (attr: string): string => spawnSync(
|
|
||||||
['nix', 'eval', '--raw', `${FLAKE}#${attr}.version`].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString();
|
|
||||||
|
|
||||||
export default (
|
|
||||||
attr: string,
|
|
||||||
scope?: string,
|
|
||||||
scopeAttr?: string,
|
|
||||||
): string | null => {
|
|
||||||
const realAttr = scope ? `${attr}.x86_64-linux.${scope}.${scopeAttr}` : attr;
|
|
||||||
const cleanAttr = scope ? `${attr}.${scope}.${scopeAttr}` : attr;
|
|
||||||
|
|
||||||
console.log(styleText(['magenta'], `\nUpdating ${cleanAttr}:\n`));
|
|
||||||
|
|
||||||
const OLD_VERSION = getAttrVersion(realAttr);
|
|
||||||
|
|
||||||
spawnSync('nix-update', ['--flake', realAttr, '-u'], { cwd: FLAKE, stdio: 'inherit' });
|
|
||||||
|
|
||||||
const NEW_VERSION = getAttrVersion(realAttr);
|
|
||||||
|
|
||||||
return OLD_VERSION !== NEW_VERSION ?
|
|
||||||
`${cleanAttr}: ${OLD_VERSION} -> ${NEW_VERSION}` :
|
|
||||||
null;
|
|
||||||
};
|
|
|
@ -1,123 +0,0 @@
|
||||||
import { readPackageJSON, writePackageJSON } from 'pkg-types';
|
|
||||||
import { accessSync, constants, existsSync } from 'node:fs';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
import { replaceInFile, npmRun } from './lib';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE as string;
|
|
||||||
|
|
||||||
const PINS = new Map([]);
|
|
||||||
|
|
||||||
const updatePackageJson = async(workspaceDir: string, updates: object) => {
|
|
||||||
const currentPackageJson = await readPackageJSON(`${workspaceDir}/package.json`);
|
|
||||||
|
|
||||||
const outdated = JSON.parse(npmRun(['outdated', '--json'], workspaceDir));
|
|
||||||
|
|
||||||
const updateDeps = (deps: string) => {
|
|
||||||
Object.keys(currentPackageJson[deps]).forEach(async(dep) => {
|
|
||||||
if (dep === 'astal') {
|
|
||||||
const latestCommit = JSON.parse(spawnSync(
|
|
||||||
['curl', '-s', 'https://api.github.com/repos/Aylur/astal/commits/main'].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString()).sha;
|
|
||||||
|
|
||||||
currentPackageJson[deps][dep] = `https://gitpkg.vercel.app/Aylur/astal/lang/gjs/src?${latestCommit}`;
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (PINS.has(dep)) {
|
|
||||||
currentPackageJson[deps][dep] = PINS.get(dep);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
const versions = outdated[dep];
|
|
||||||
const current = versions?.wanted || versions?.current;
|
|
||||||
|
|
||||||
if (!current) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (current !== versions.latest) {
|
|
||||||
updates[dep] = `${current} -> ${versions.latest}`;
|
|
||||||
}
|
|
||||||
|
|
||||||
currentPackageJson[deps][dep] = versions.latest;
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
if (currentPackageJson.dependencies) {
|
|
||||||
updateDeps('dependencies');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (currentPackageJson.devDependencies) {
|
|
||||||
updateDeps('devDependencies');
|
|
||||||
}
|
|
||||||
|
|
||||||
await writePackageJSON(`${workspaceDir}/package.json`, currentPackageJson);
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
const prefetchNpmDeps = (workspaceDir: string): string => {
|
|
||||||
npmRun(['update', '--package-lock-only'], workspaceDir);
|
|
||||||
|
|
||||||
return spawnSync(
|
|
||||||
'prefetch-npm-deps',
|
|
||||||
[`${workspaceDir}/package-lock.json`],
|
|
||||||
).stdout.toString().replace('\n', '');
|
|
||||||
};
|
|
||||||
|
|
||||||
|
|
||||||
export default async(): Promise<string | null> => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating node modules:\n'));
|
|
||||||
|
|
||||||
const updates = {};
|
|
||||||
|
|
||||||
const packages = spawnSync('find', [FLAKE, '-name', 'package.json']).stdout.toString().split('\n')
|
|
||||||
.filter((f) => f !== '')
|
|
||||||
.filter((f) => ![
|
|
||||||
'.direnv',
|
|
||||||
'node_modules',
|
|
||||||
'results',
|
|
||||||
].some((dirName) => f.includes(dirName)));
|
|
||||||
|
|
||||||
for (const path of packages) {
|
|
||||||
console.log(path);
|
|
||||||
|
|
||||||
try {
|
|
||||||
accessSync(path, constants.R_OK | constants.W_OK);
|
|
||||||
|
|
||||||
const parentPath = path.replace('/package.json', '');
|
|
||||||
|
|
||||||
await updatePackageJson(parentPath, updates);
|
|
||||||
|
|
||||||
if (existsSync(`${parentPath}/default.nix`)) {
|
|
||||||
const hash = prefetchNpmDeps(parentPath);
|
|
||||||
|
|
||||||
replaceInFile(
|
|
||||||
/npmDepsHash = ".*";/,
|
|
||||||
`npmDepsHash = "${hash}";`,
|
|
||||||
`${parentPath}/default.nix`,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Make sure we update the apps' config package-lock.json
|
|
||||||
if (parentPath.includes('apps/config')) {
|
|
||||||
npmRun(['i'], parentPath);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (e) {
|
|
||||||
console.warn(`Could not write to ${path}`);
|
|
||||||
console.warn(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return Object.entries(updates).length > 0 ?
|
|
||||||
Object.entries(updates)
|
|
||||||
.map(([key, dep]) => `${key}: ${dep}`)
|
|
||||||
.join('\n') :
|
|
||||||
null;
|
|
||||||
};
|
|
|
@ -1,44 +0,0 @@
|
||||||
import { writeFileSync } from 'node:fs';
|
|
||||||
import { spawnSync } from 'node:child_process';
|
|
||||||
import { styleText } from 'node:util';
|
|
||||||
|
|
||||||
import { parseFetchurl } from './lib';
|
|
||||||
|
|
||||||
|
|
||||||
/* Constants */
|
|
||||||
const FLAKE = process.env.FLAKE;
|
|
||||||
|
|
||||||
const genVueText = (
|
|
||||||
version: string,
|
|
||||||
hash: string,
|
|
||||||
url: string,
|
|
||||||
) => `# This file was autogenerated. DO NOT EDIT!
|
|
||||||
{
|
|
||||||
version = "${version}";
|
|
||||||
url = "${url}";
|
|
||||||
hash = "${hash}";
|
|
||||||
}
|
|
||||||
`;
|
|
||||||
|
|
||||||
export default (): string | null => {
|
|
||||||
console.log(styleText(['magenta'], '\nUpdating Vuetorrent:\n'));
|
|
||||||
|
|
||||||
const FILE = `${FLAKE}/configurations/nos/modules/qbittorrent/vuetorrent.nix`;
|
|
||||||
|
|
||||||
const OLD_VERSION = JSON.parse(spawnSync(
|
|
||||||
['nix', 'eval', '-f', FILE, '--json'].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString()).version;
|
|
||||||
|
|
||||||
const VERSION = JSON.parse(spawnSync(
|
|
||||||
['curl', '-s', 'https://api.github.com/repos/VueTorrent/VueTorrent/releases/latest'].join(' '), [], { shell: true },
|
|
||||||
).stdout.toString()).tag_name.replace('v', '');
|
|
||||||
|
|
||||||
const URL = `https://github.com/VueTorrent/VueTorrent/releases/download/v${VERSION}/vuetorrent.zip`;
|
|
||||||
const HASH = parseFetchurl(URL);
|
|
||||||
|
|
||||||
const fileText = genVueText(VERSION, HASH, URL);
|
|
||||||
|
|
||||||
writeFileSync(FILE, fileText);
|
|
||||||
|
|
||||||
return OLD_VERSION !== VERSION ? `Vuetorrent: ${OLD_VERSION} -> ${VERSION}\n` : null;
|
|
||||||
};
|
|
|
@ -1,10 +0,0 @@
|
||||||
{
|
|
||||||
"$schema": "https://json.schemastore.org/tsconfig",
|
|
||||||
"extends": "../config/tsconfig.base.json",
|
|
||||||
"includes": [
|
|
||||||
"*.ts",
|
|
||||||
"**/*.ts",
|
|
||||||
"*.js",
|
|
||||||
"**/*.js"
|
|
||||||
]
|
|
||||||
}
|
|
126
common/default.nix
Normal file
126
common/default.nix
Normal file
|
@ -0,0 +1,126 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
home-manager,
|
||||||
|
lib,
|
||||||
|
nh,
|
||||||
|
nix-melt,
|
||||||
|
nur,
|
||||||
|
nurl,
|
||||||
|
pkgs,
|
||||||
|
...
|
||||||
|
} @ inputs: {
|
||||||
|
imports = [
|
||||||
|
./vars
|
||||||
|
|
||||||
|
./modules
|
||||||
|
./pkgs
|
||||||
|
|
||||||
|
nur.nixosModules.nur
|
||||||
|
nh.nixosModules.default
|
||||||
|
home-manager.nixosModules.home-manager
|
||||||
|
|
||||||
|
../modules/arion
|
||||||
|
../modules/borgbackup
|
||||||
|
../modules/nvidia.nix
|
||||||
|
];
|
||||||
|
|
||||||
|
nixpkgs = {
|
||||||
|
config.allowUnfree = true;
|
||||||
|
overlays = import ./overlays inputs;
|
||||||
|
};
|
||||||
|
boot.tmp.cleanOnBoot = true;
|
||||||
|
|
||||||
|
nix = {
|
||||||
|
# Allow deleting store files with '.' in the name
|
||||||
|
package = pkgs.nix.overrideAttrs (o: {
|
||||||
|
patches =
|
||||||
|
(o.patches or [])
|
||||||
|
++ [
|
||||||
|
./overlays/nix/patch
|
||||||
|
];
|
||||||
|
});
|
||||||
|
# Edit nix.conf
|
||||||
|
settings = {
|
||||||
|
# Store
|
||||||
|
keep-outputs = true;
|
||||||
|
keep-derivations = true;
|
||||||
|
auto-optimise-store = true;
|
||||||
|
|
||||||
|
# Commands
|
||||||
|
experimental-features = ["nix-command" "flakes"];
|
||||||
|
http-connections = 0; # unlimited for local cache
|
||||||
|
warn-dirty = false;
|
||||||
|
show-trace = true;
|
||||||
|
|
||||||
|
# remote building
|
||||||
|
trusted-users = ["matt" "nixremote"];
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
nh = {
|
||||||
|
enable = true;
|
||||||
|
# weekly cleanup
|
||||||
|
clean = {
|
||||||
|
enable = true;
|
||||||
|
extraArgs = "--keep-since 30d";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
services = {
|
||||||
|
fwupd.enable = true;
|
||||||
|
|
||||||
|
xserver.xkb = {
|
||||||
|
layout = "ca";
|
||||||
|
variant = "multix";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home-manager = let
|
||||||
|
inherit (config.vars) mainUser;
|
||||||
|
mainUserConf = config.home-manager.users.${mainUser};
|
||||||
|
|
||||||
|
default = {
|
||||||
|
imports = [
|
||||||
|
# Make the vars be the same on Nix and HM
|
||||||
|
{
|
||||||
|
options.vars = lib.mkOption {
|
||||||
|
type = lib.types.attrs;
|
||||||
|
readOnly = true;
|
||||||
|
default = config.vars;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
nur.hmModules.nur
|
||||||
|
|
||||||
|
./home
|
||||||
|
./home/trash-d
|
||||||
|
./pkgs
|
||||||
|
];
|
||||||
|
|
||||||
|
home.packages =
|
||||||
|
[
|
||||||
|
nix-melt.packages.${pkgs.system}.default
|
||||||
|
nurl.packages.${pkgs.system}.default
|
||||||
|
]
|
||||||
|
++ (with config.nur.repos.rycee; [
|
||||||
|
mozilla-addons-to-nix
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
in {
|
||||||
|
users = {
|
||||||
|
root =
|
||||||
|
default
|
||||||
|
// {
|
||||||
|
home.stateVersion = mainUserConf.home.stateVersion;
|
||||||
|
};
|
||||||
|
greeter =
|
||||||
|
lib.mkIf (config.services.greetd.enable)
|
||||||
|
(default
|
||||||
|
// {
|
||||||
|
home.stateVersion = mainUserConf.home.stateVersion;
|
||||||
|
});
|
||||||
|
|
||||||
|
${mainUser} = default;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
145
common/home/bash/default.nix
Normal file
145
common/home/bash/default.nix
Normal file
|
@ -0,0 +1,145 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
lib,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (lib) concatStrings fileContents;
|
||||||
|
inherit (config.vars) promptColors;
|
||||||
|
in {
|
||||||
|
imports = [./programs.nix];
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
starship = {
|
||||||
|
enable = true;
|
||||||
|
enableBashIntegration = true;
|
||||||
|
|
||||||
|
settings = {
|
||||||
|
format = concatStrings [
|
||||||
|
"╭╴"
|
||||||
|
"[](fg:${promptColors.firstColor})"
|
||||||
|
"[ ](bg:${promptColors.firstColor} fg:#090c0c)"
|
||||||
|
"[](bg:${promptColors.secondColor} fg:${promptColors.firstColor})"
|
||||||
|
"$username$hostname"
|
||||||
|
"[](fg:${promptColors.secondColor} bg:${promptColors.thirdColor})"
|
||||||
|
"$directory"
|
||||||
|
"[](fg:${promptColors.thirdColor} bg:${promptColors.fourthColor})"
|
||||||
|
"$git_branch"
|
||||||
|
"[](fg:${promptColors.fourthColor})$shlvl$nix_shell"
|
||||||
|
"\n╰╴$character"
|
||||||
|
];
|
||||||
|
|
||||||
|
username = {
|
||||||
|
show_always = true;
|
||||||
|
style_user = "fg:${promptColors.textColor} bg:${promptColors.secondColor}";
|
||||||
|
style_root = "fg:red bg:${promptColors.secondColor} blink";
|
||||||
|
format = "[ $user]($style)";
|
||||||
|
};
|
||||||
|
|
||||||
|
hostname = {
|
||||||
|
ssh_only = false;
|
||||||
|
style = "fg:${promptColors.textColor} bg:${promptColors.secondColor}";
|
||||||
|
format = "[@$hostname ]($style)";
|
||||||
|
};
|
||||||
|
|
||||||
|
directory = {
|
||||||
|
style = "fg:${promptColors.firstColor} bg:${promptColors.thirdColor}";
|
||||||
|
format = "[ $path ]($style)";
|
||||||
|
truncate_to_repo = false;
|
||||||
|
truncation_length = 0;
|
||||||
|
|
||||||
|
substitutions = {
|
||||||
|
"Documents" = " ";
|
||||||
|
"Downloads" = " ";
|
||||||
|
"Music" = " ";
|
||||||
|
"Pictures" = " ";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
git_branch = {
|
||||||
|
style = "fg:${promptColors.secondColor} bg:${promptColors.fourthColor}";
|
||||||
|
symbol = "";
|
||||||
|
format = "[ $symbol $branch ]($style)";
|
||||||
|
};
|
||||||
|
|
||||||
|
shlvl = {
|
||||||
|
disabled = false;
|
||||||
|
repeat = true;
|
||||||
|
symbol = " ";
|
||||||
|
format = "[ $symbol]($style)";
|
||||||
|
threshold = 1;
|
||||||
|
};
|
||||||
|
|
||||||
|
nix_shell = {
|
||||||
|
symbol = "❄️ ";
|
||||||
|
format = "[ $symbol]($style)";
|
||||||
|
};
|
||||||
|
|
||||||
|
character = {
|
||||||
|
success_symbol = "[\\$](bold green)";
|
||||||
|
error_symbol = "[\\$](bold red)";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
bash = {
|
||||||
|
enable = true;
|
||||||
|
enableCompletion = true;
|
||||||
|
|
||||||
|
historyFile = "\$HOME/.cache/.bash_history";
|
||||||
|
historyFileSize = 100000; # default
|
||||||
|
historySize = 10000; # default
|
||||||
|
historyControl = [
|
||||||
|
"erasedups"
|
||||||
|
"ignorespace"
|
||||||
|
];
|
||||||
|
historyIgnore = [
|
||||||
|
"ls"
|
||||||
|
"exit"
|
||||||
|
"logout"
|
||||||
|
];
|
||||||
|
|
||||||
|
shellOptions = [
|
||||||
|
"histappend"
|
||||||
|
"checkwinsize"
|
||||||
|
"extglob"
|
||||||
|
"globstar"
|
||||||
|
"checkjobs"
|
||||||
|
"autocd"
|
||||||
|
"cdspell"
|
||||||
|
"dirspell"
|
||||||
|
"dotglob"
|
||||||
|
];
|
||||||
|
|
||||||
|
shellAliases = {
|
||||||
|
# Add whitespace after, to allow
|
||||||
|
# sudo to inherit all other aliases
|
||||||
|
sudo = "sudo ";
|
||||||
|
|
||||||
|
ls = "ls -lah --color=auto";
|
||||||
|
tree = "tree -a -I node_modules";
|
||||||
|
cp = "cp -r";
|
||||||
|
};
|
||||||
|
|
||||||
|
#profileExtra = ''
|
||||||
|
#'';
|
||||||
|
bashrcExtra =
|
||||||
|
/*
|
||||||
|
bash
|
||||||
|
*/
|
||||||
|
''
|
||||||
|
# Check if shell is interactive
|
||||||
|
[[ $- == *i* ]] || return 0
|
||||||
|
|
||||||
|
${fileContents ./config/dracula/less.sh}
|
||||||
|
${fileContents ./config/dracula/fzf.sh}
|
||||||
|
|
||||||
|
${fileContents ./config/colorgrid.sh}
|
||||||
|
${fileContents ./config/bashrc}
|
||||||
|
'';
|
||||||
|
#initExtra = ''
|
||||||
|
#'';
|
||||||
|
#logoutExtra = ''
|
||||||
|
#'';
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
|
@ -1,14 +1,9 @@
|
||||||
self: {
|
{
|
||||||
config,
|
|
||||||
lib,
|
|
||||||
pkgs,
|
pkgs,
|
||||||
|
config,
|
||||||
...
|
...
|
||||||
}: let
|
}: {
|
||||||
inherit (lib) attrValues mkIf;
|
programs = {
|
||||||
|
|
||||||
cfg = config.programs.bash;
|
|
||||||
in {
|
|
||||||
config.programs = mkIf cfg.enable {
|
|
||||||
fzf = {
|
fzf = {
|
||||||
enable = true;
|
enable = true;
|
||||||
enableBashIntegration = true;
|
enableBashIntegration = true;
|
||||||
|
@ -46,16 +41,18 @@ in {
|
||||||
|
|
||||||
bat = {
|
bat = {
|
||||||
enable = true;
|
enable = true;
|
||||||
|
config = {
|
||||||
config.theme = "dracula-bat";
|
theme = "dracula-bat";
|
||||||
themes.dracula-bat.src = pkgs.scopedPackages.dracula.bat;
|
|
||||||
|
|
||||||
extraPackages = attrValues {
|
|
||||||
inherit (pkgs.bat-extras) batman;
|
|
||||||
};
|
};
|
||||||
|
themes = {
|
||||||
|
dracula-bat = {
|
||||||
|
src = pkgs.dracula-theme;
|
||||||
|
file = "bat";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
extraPackages = with pkgs.bat-extras; [
|
||||||
|
batman
|
||||||
|
];
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
# For accurate stack trace
|
|
||||||
_file = ./default.nix;
|
|
||||||
}
|
}
|
11
common/home/default.nix
Normal file
11
common/home/default.nix
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
{...}: {
|
||||||
|
imports = [
|
||||||
|
./bash
|
||||||
|
./direnv
|
||||||
|
./git
|
||||||
|
./neovim
|
||||||
|
./nix-index
|
||||||
|
./tmux
|
||||||
|
./packages.nix
|
||||||
|
];
|
||||||
|
}
|
10
common/home/direnv/default.nix
Normal file
10
common/home/direnv/default.nix
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
{pkgs, ...}: {
|
||||||
|
programs.direnv = {
|
||||||
|
enable = true;
|
||||||
|
enableBashIntegration = true;
|
||||||
|
nix-direnv = {
|
||||||
|
enable = true;
|
||||||
|
package = pkgs.nix-direnv-flakes;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
82
common/home/git/default.nix
Normal file
82
common/home/git/default.nix
Normal file
|
@ -0,0 +1,82 @@
|
||||||
|
{pkgs, ...}: {
|
||||||
|
programs = {
|
||||||
|
git = {
|
||||||
|
enable = true;
|
||||||
|
lfs.enable = true;
|
||||||
|
|
||||||
|
includes = [
|
||||||
|
{path = "${pkgs.dracula-theme}/git-colors";}
|
||||||
|
|
||||||
|
{
|
||||||
|
condition = "hasconfig:remote.*.url:git@github.com:*/**";
|
||||||
|
contents = {
|
||||||
|
user = {
|
||||||
|
email = "matt@nelim.org";
|
||||||
|
name = "matt1432";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
condition = "hasconfig:remote.*.url:git@git.nelim.org:*/**";
|
||||||
|
contents = {
|
||||||
|
user = {
|
||||||
|
email = "matt@nelim.org";
|
||||||
|
name = "matt1432";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
condition = "hasconfig:remote.*.url:git@gitlab.info.uqam.ca:*/**";
|
||||||
|
contents = {
|
||||||
|
user = {
|
||||||
|
email = "gj591944@ens.uqam.ca";
|
||||||
|
name = "Mathis Hurtubise";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
];
|
||||||
|
|
||||||
|
delta = {
|
||||||
|
enable = true;
|
||||||
|
options = {
|
||||||
|
side-by-side = true;
|
||||||
|
line-numbers-zero-style = "#E6EDF3"; #BD93F9";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = {
|
||||||
|
diff.sopsdiffer.textconv = "sops --config /dev/null -d";
|
||||||
|
|
||||||
|
# https://github.com/dandavison/delta/issues/630#issuecomment-860046929
|
||||||
|
pager = let
|
||||||
|
cmd = "LESS='LRc --mouse' ${pkgs.delta}/bin/delta";
|
||||||
|
in {
|
||||||
|
diff = cmd;
|
||||||
|
show = cmd;
|
||||||
|
stash = cmd;
|
||||||
|
log = cmd;
|
||||||
|
reflog = cmd;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
home.packages = with pkgs; [
|
||||||
|
(writeShellApplication {
|
||||||
|
name = "chore";
|
||||||
|
runtimeInputs = [git];
|
||||||
|
|
||||||
|
text = ''
|
||||||
|
DIR=''${1:-"$FLAKE"}
|
||||||
|
|
||||||
|
cd "$DIR" || exit 1
|
||||||
|
|
||||||
|
git add flake.lock
|
||||||
|
git commit -m 'chore: update flake.lock'
|
||||||
|
git push
|
||||||
|
'';
|
||||||
|
})
|
||||||
|
];
|
||||||
|
}
|
2
common/home/neovim/base.lua
Normal file
2
common/home/neovim/base.lua
Normal file
|
@ -0,0 +1,2 @@
|
||||||
|
-- Add `:Format` command to format current buffer
|
||||||
|
vim.api.nvim_create_user_command("Format", "call CocAction('format')", {})
|
34
common/home/neovim/base.vim
Normal file
34
common/home/neovim/base.vim
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
" by default, the indent is 2 spaces.
|
||||||
|
set smartindent
|
||||||
|
set expandtab
|
||||||
|
set shiftwidth=2
|
||||||
|
set softtabstop=2
|
||||||
|
set tabstop=2
|
||||||
|
|
||||||
|
" for html/rb files, 2 spaces
|
||||||
|
autocmd Filetype html setlocal ts=2 sw=2 expandtab
|
||||||
|
autocmd Filetype ruby setlocal ts=2 sw=2 expandtab
|
||||||
|
|
||||||
|
" for js/coffee/jade files, 4 spaces
|
||||||
|
autocmd Filetype javascript setlocal ts=4 sw=4 sts=0 expandtab
|
||||||
|
autocmd Filetype typescript setlocal ts=4 sw=4 sts=0 expandtab
|
||||||
|
autocmd Filetype java setlocal ts=4 sw=4 sts=0 expandtab
|
||||||
|
autocmd Filetype sh setlocal ts=4 sw=4 sts=0 expandtab
|
||||||
|
autocmd Filetype hyprlang setlocal ts=4 sw=4 sts=0 expandtab
|
||||||
|
|
||||||
|
" support scss @
|
||||||
|
autocmd FileType scss setl iskeyword+=@-@
|
||||||
|
|
||||||
|
set number
|
||||||
|
set relativenumber
|
||||||
|
|
||||||
|
" TODO: make this work for nix-on-droid
|
||||||
|
set undofile
|
||||||
|
set undodir=/home/matt/.cache/nvim/
|
||||||
|
|
||||||
|
" remove highlight on words
|
||||||
|
nnoremap <silent> <esc> :noh<cr><esc>
|
||||||
|
|
||||||
|
" Always show the signcolumn, otherwise it would shift the text each time
|
||||||
|
" diagnostics appear/become resolved
|
||||||
|
set signcolumn=yes
|
340
common/home/neovim/default.nix
Normal file
340
common/home/neovim/default.nix
Normal file
|
@ -0,0 +1,340 @@
|
||||||
|
{
|
||||||
|
config,
|
||||||
|
pkgs,
|
||||||
|
lib,
|
||||||
|
nvim-theme-src,
|
||||||
|
coc-stylelintplus,
|
||||||
|
vimplugin-riscv-src,
|
||||||
|
...
|
||||||
|
}: let
|
||||||
|
inherit (config.vars) neovimIde;
|
||||||
|
inherit (lib) fileContents hasAttr optionalAttrs optionals;
|
||||||
|
|
||||||
|
javaSdk = pkgs.temurin-bin-17;
|
||||||
|
coc-stylelintplus-flake = coc-stylelintplus.packages.${pkgs.system}.default;
|
||||||
|
in {
|
||||||
|
home = optionalAttrs neovimIde {
|
||||||
|
packages = with pkgs; [
|
||||||
|
gradle
|
||||||
|
maven
|
||||||
|
alejandra
|
||||||
|
];
|
||||||
|
};
|
||||||
|
|
||||||
|
xdg.dataFile = optionalAttrs neovimIde {
|
||||||
|
".gradle/gradle.properties".text = ''
|
||||||
|
org.gradle.java.home = ${javaSdk}
|
||||||
|
'';
|
||||||
|
};
|
||||||
|
|
||||||
|
programs = {
|
||||||
|
java = optionalAttrs neovimIde {
|
||||||
|
enable = true;
|
||||||
|
package = javaSdk;
|
||||||
|
};
|
||||||
|
|
||||||
|
# I love doing typos
|
||||||
|
bash.shellAliases = {
|
||||||
|
nivm = "nvim";
|
||||||
|
nivim = "nvim";
|
||||||
|
};
|
||||||
|
|
||||||
|
neovim = {
|
||||||
|
enable = true;
|
||||||
|
withNodeJs = true;
|
||||||
|
withPython3 = true;
|
||||||
|
withRuby = false;
|
||||||
|
|
||||||
|
defaultEditor = true;
|
||||||
|
viAlias = true;
|
||||||
|
vimAlias = true;
|
||||||
|
|
||||||
|
extraPackages = with pkgs; ([
|
||||||
|
bat
|
||||||
|
gcc
|
||||||
|
]
|
||||||
|
++ optionals neovimIde [
|
||||||
|
nodejs_latest
|
||||||
|
nodePackages.npm
|
||||||
|
nodePackages.neovim
|
||||||
|
gradle
|
||||||
|
nil
|
||||||
|
]);
|
||||||
|
|
||||||
|
extraPython3Packages = ps:
|
||||||
|
optionals neovimIde [
|
||||||
|
ps.pylint
|
||||||
|
];
|
||||||
|
|
||||||
|
coc = optionalAttrs neovimIde {
|
||||||
|
enable = true;
|
||||||
|
settings = {
|
||||||
|
# General
|
||||||
|
colors.enable = true;
|
||||||
|
coc.preferences.formatOnType = true;
|
||||||
|
diagnostic.checkCurrentLine = true;
|
||||||
|
inlayHint.enable = false;
|
||||||
|
|
||||||
|
# ESLint
|
||||||
|
eslint = {
|
||||||
|
format.enable = true;
|
||||||
|
autoFixOnSave = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
# Stylelint
|
||||||
|
stylelintplus = {
|
||||||
|
enable = true;
|
||||||
|
cssInJs = true;
|
||||||
|
autoFixOnSave = true;
|
||||||
|
autoFixOnFormat = true;
|
||||||
|
};
|
||||||
|
css.validate = false;
|
||||||
|
less.validate = false;
|
||||||
|
scss.validate = false;
|
||||||
|
wxss.validate = false;
|
||||||
|
|
||||||
|
# Lua
|
||||||
|
Lua = {
|
||||||
|
misc.parameters = [
|
||||||
|
"--metapath"
|
||||||
|
"~/.cache/sumneko_lua/meta"
|
||||||
|
"--logpath"
|
||||||
|
"~/.cache/sumneko_lua/log"
|
||||||
|
];
|
||||||
|
workspace.library = [
|
||||||
|
"$\{3rd\}/luv/library"
|
||||||
|
];
|
||||||
|
};
|
||||||
|
sumneko-lua = {
|
||||||
|
serverDir = "${pkgs.lua-language-server}/share/lua-language-server";
|
||||||
|
enableNvimLuaDev = true;
|
||||||
|
};
|
||||||
|
|
||||||
|
languageserver = {
|
||||||
|
# Nix
|
||||||
|
nix = {
|
||||||
|
command = "nil";
|
||||||
|
filetypes = ["nix"];
|
||||||
|
rootPatterns = ["flake.nix"];
|
||||||
|
settings = {
|
||||||
|
nil = {
|
||||||
|
formatting.command = ["alejandra"];
|
||||||
|
|
||||||
|
nix = {
|
||||||
|
maxMemoryMB = 2560;
|
||||||
|
flake.autoArchive = hasAttr "sops" config;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Java
|
||||||
|
java = {
|
||||||
|
maven.downloadSources = true;
|
||||||
|
eclipse.downloadSources = true;
|
||||||
|
|
||||||
|
format.settings.url = "eclipse-formatter.xml";
|
||||||
|
|
||||||
|
jdt.ls = {
|
||||||
|
java.home = "${javaSdk}";
|
||||||
|
statusIcons = {
|
||||||
|
"busy" = "Busy";
|
||||||
|
"ready" = "OK";
|
||||||
|
"warning" = "Warning";
|
||||||
|
"error" = "Error";
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
# Bash
|
||||||
|
bashIde.shellcheckPath = "${pkgs.shellcheck}/bin/shellcheck";
|
||||||
|
|
||||||
|
markdownlint.config = {
|
||||||
|
no-trailing-spaces = true;
|
||||||
|
no-multiple-blanks = false;
|
||||||
|
no-duplicate-heading = false;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
extraConfig = fileContents ./base.vim;
|
||||||
|
extraLuaConfig = fileContents ./base.lua;
|
||||||
|
|
||||||
|
plugins = with pkgs.vimPlugins;
|
||||||
|
([
|
||||||
|
fzfWrapper
|
||||||
|
fzf-vim
|
||||||
|
fugitive
|
||||||
|
|
||||||
|
{
|
||||||
|
plugin = dracula-nvim.overrideAttrs {
|
||||||
|
src = nvim-theme-src;
|
||||||
|
};
|
||||||
|
type = "viml";
|
||||||
|
config = fileContents ./plugins/dracula.vim;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = todo-comments-nvim;
|
||||||
|
type = "lua";
|
||||||
|
config =
|
||||||
|
/*
|
||||||
|
lua
|
||||||
|
*/
|
||||||
|
''require('todo-comments').setup()'';
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = gitsigns-nvim;
|
||||||
|
type = "lua";
|
||||||
|
config = fileContents ./plugins/gitsigns.lua;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = indent-blankline-nvim;
|
||||||
|
type = "lua";
|
||||||
|
config = fileContents ./plugins/indent.lua;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = mini-nvim;
|
||||||
|
type = "lua";
|
||||||
|
config = fileContents ./plugins/mini.lua;
|
||||||
|
}
|
||||||
|
]
|
||||||
|
++ optionals neovimIde [
|
||||||
|
markdown-preview-nvim
|
||||||
|
|
||||||
|
# Coc configured
|
||||||
|
coc-css
|
||||||
|
coc-eslint
|
||||||
|
coc-java
|
||||||
|
coc-sh
|
||||||
|
coc-stylelintplus-flake
|
||||||
|
{
|
||||||
|
plugin = coc-snippets;
|
||||||
|
type = "viml";
|
||||||
|
config = fileContents ./plugins/snippets.vim;
|
||||||
|
}
|
||||||
|
|
||||||
|
## Lua
|
||||||
|
coc-sumneko-lua
|
||||||
|
neodev-nvim
|
||||||
|
|
||||||
|
## Fzf
|
||||||
|
coc-fzf
|
||||||
|
|
||||||
|
coc-highlight
|
||||||
|
coc-json
|
||||||
|
coc-pyright
|
||||||
|
coc-vimlsp
|
||||||
|
coc-yaml
|
||||||
|
coc-toml
|
||||||
|
coc-markdownlint
|
||||||
|
coc-tsserver
|
||||||
|
|
||||||
|
{
|
||||||
|
plugin = nvim-autopairs;
|
||||||
|
type = "lua";
|
||||||
|
config = fileContents ./plugins/autopairs.lua;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = lualine-nvim;
|
||||||
|
type = "lua";
|
||||||
|
config = fileContents ./plugins/lualine.lua;
|
||||||
|
}
|
||||||
|
{
|
||||||
|
plugin = neo-tree-nvim;
|
||||||
|
type = "viml";
|
||||||
|
config = ''
|
||||||
|
${fileContents ./plugins/neotree.vim}
|
||||||
|
|
||||||
|
lua << EOF
|
||||||
|
${fileContents ./plugins/neotree.lua}
|
||||||
|
EOF
|
||||||
|
'';
|
||||||
|
}
|
||||||
|
(pkgs.vimUtils.buildVimPlugin {
|
||||||
|
name = "riscv-asm";
|
||||||
|
src = vimplugin-riscv-src;
|
||||||
|
})
|
||||||
|
])
|
||||||
|
# Treesitter
|
||||||
|
++ (with pkgs.vimPlugins; [
|
||||||
|
nvim-treesitter-context
|
||||||
|
nvim-treesitter-textobjects
|
||||||
|
{
|
||||||
|
type = "viml";
|
||||||
|
config = fileContents ./plugins/treesitter.vim;
|
||||||
|
plugin = nvim-treesitter.withPlugins (p: [
|
||||||
|
p.awk
|
||||||
|
p.bash
|
||||||
|
p.c
|
||||||
|
p.c_sharp
|
||||||
|
p.cairo
|
||||||
|
p.cmake
|
||||||
|
p.comment
|
||||||
|
p.cpp
|
||||||
|
p.css
|
||||||
|
p.csv
|
||||||
|
p.cuda
|
||||||
|
p.diff
|
||||||
|
p.dockerfile
|
||||||
|
p.dot
|
||||||
|
p.git_config
|
||||||
|
p.git_rebase
|
||||||
|
p.gitattributes
|
||||||
|
p.gitcommit
|
||||||
|
p.gitignore
|
||||||
|
p.go
|
||||||
|
p.gomod
|
||||||
|
p.gosum
|
||||||
|
p.groovy
|
||||||
|
p.haskell
|
||||||
|
p.haskell_persistent
|
||||||
|
p.hyprlang
|
||||||
|
p.html
|
||||||
|
p.ini
|
||||||
|
p.java
|
||||||
|
p.javascript
|
||||||
|
p.jq
|
||||||
|
p.jsdoc
|
||||||
|
p.json
|
||||||
|
p.json5
|
||||||
|
p.jsonc
|
||||||
|
p.jsonnet
|
||||||
|
p.kotlin
|
||||||
|
p.latex
|
||||||
|
p.lua
|
||||||
|
p.luadoc
|
||||||
|
p.make
|
||||||
|
p.markdown
|
||||||
|
p.meson
|
||||||
|
p.ninja
|
||||||
|
p.nix
|
||||||
|
p.passwd
|
||||||
|
p.perl
|
||||||
|
p.php
|
||||||
|
p.phpdoc
|
||||||
|
p.properties
|
||||||
|
p.python
|
||||||
|
p.rasi
|
||||||
|
p.regex
|
||||||
|
p.requirements
|
||||||
|
p.ruby
|
||||||
|
p.rust
|
||||||
|
p.scss
|
||||||
|
p.sql
|
||||||
|
p.ssh_config
|
||||||
|
p.toml
|
||||||
|
p.todotxt
|
||||||
|
p.typescript
|
||||||
|
p.udev
|
||||||
|
p.vim
|
||||||
|
p.vimdoc
|
||||||
|
p.vue
|
||||||
|
p.xml
|
||||||
|
p.yaml
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
]);
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
16
common/home/neovim/plugins/autopairs.lua
Normal file
16
common/home/neovim/plugins/autopairs.lua
Normal file
|
@ -0,0 +1,16 @@
|
||||||
|
-- Auto indent when pressing Enter between brackets
|
||||||
|
local remap = vim.api.nvim_set_keymap
|
||||||
|
local npairs = require('nvim-autopairs')
|
||||||
|
npairs.setup({map_cr=false})
|
||||||
|
|
||||||
|
_G.MUtils= {}
|
||||||
|
|
||||||
|
MUtils.completion_confirm=function()
|
||||||
|
if vim.fn["coc#pum#visible"]() ~= 0 then
|
||||||
|
return vim.fn["coc#pum#confirm"]()
|
||||||
|
else
|
||||||
|
return npairs.autopairs_cr()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
remap('i' , '<CR>','v:lua.MUtils.completion_confirm()', {expr = true , noremap = true})
|
10
common/home/neovim/plugins/dracula.vim
Normal file
10
common/home/neovim/plugins/dracula.vim
Normal file
|
@ -0,0 +1,10 @@
|
||||||
|
" set dot icon in place of trailing whitespaces
|
||||||
|
set list listchars=tab:\ \ ,nbsp:␣,trail:•,extends:⟩,precedes:⟨
|
||||||
|
|
||||||
|
|
||||||
|
lua << EOF
|
||||||
|
-- Add visual indicator for trailing whitespaces
|
||||||
|
vim.opt.fillchars = {eob = " "}
|
||||||
|
|
||||||
|
vim.cmd[[colorscheme dracula]]
|
||||||
|
EOF
|
13
common/home/neovim/plugins/gitsigns.lua
Normal file
13
common/home/neovim/plugins/gitsigns.lua
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
local gitsigns = require("gitsigns")
|
||||||
|
|
||||||
|
local function visual_stage()
|
||||||
|
local first_line = vim.fn.line('v')
|
||||||
|
local last_line = vim.fn.getpos('.')[2]
|
||||||
|
gitsigns.stage_hunk({ first_line, last_line })
|
||||||
|
end
|
||||||
|
|
||||||
|
vim.keymap.set("v", "gs", function()
|
||||||
|
visual_stage()
|
||||||
|
end)
|
||||||
|
|
||||||
|
gitsigns.setup();
|
26
common/home/neovim/plugins/indent.lua
Normal file
26
common/home/neovim/plugins/indent.lua
Normal file
|
@ -0,0 +1,26 @@
|
||||||
|
local highlight = {
|
||||||
|
"RainbowRed",
|
||||||
|
"RainbowYellow",
|
||||||
|
"RainbowBlue",
|
||||||
|
"RainbowOrange",
|
||||||
|
"RainbowGreen",
|
||||||
|
"RainbowViolet",
|
||||||
|
"RainbowCyan",
|
||||||
|
}
|
||||||
|
local hooks = require('ibl.hooks')
|
||||||
|
hooks.register(hooks.type.HIGHLIGHT_SETUP, function()
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowRed", { fg = "#E06C75" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowYellow", { fg = "#E5C07B" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowBlue", { fg = "#61AFEF" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowOrange", { fg = "#D19A66" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowGreen", { fg = "#98C379" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowViolet", { fg = "#C678DD" })
|
||||||
|
vim.api.nvim_set_hl(0, "RainbowCyan", { fg = "#56B6C2" })
|
||||||
|
end)
|
||||||
|
|
||||||
|
require('ibl').setup({
|
||||||
|
indent = {
|
||||||
|
highlight = highlight,
|
||||||
|
char = "▏",
|
||||||
|
},
|
||||||
|
})
|
9
common/home/neovim/plugins/lualine.lua
Normal file
9
common/home/neovim/plugins/lualine.lua
Normal file
|
@ -0,0 +1,9 @@
|
||||||
|
require('lualine').setup({
|
||||||
|
options = {
|
||||||
|
theme = 'dracula',
|
||||||
|
globalstatus = true,
|
||||||
|
},
|
||||||
|
sections = {
|
||||||
|
lualine_x = {'g:coc_status', 'bo:filetype'},
|
||||||
|
}
|
||||||
|
})
|
23
common/home/neovim/plugins/mini.lua
Normal file
23
common/home/neovim/plugins/mini.lua
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
local map = require('mini.map')
|
||||||
|
map.setup({
|
||||||
|
integrations = {
|
||||||
|
map.gen_integration.builtin_search(),
|
||||||
|
map.gen_integration.gitsigns(),
|
||||||
|
map.gen_integration.diagnostic(),
|
||||||
|
},
|
||||||
|
window = {
|
||||||
|
focusable = false,
|
||||||
|
width = 7,
|
||||||
|
winblend = 75,
|
||||||
|
},
|
||||||
|
})
|
||||||
|
|
||||||
|
local ts_input = require('mini.surround').gen_spec.input.treesitter
|
||||||
|
require('mini.surround').setup({
|
||||||
|
custom_surroundings = {
|
||||||
|
-- Use tree-sitter to search for function call
|
||||||
|
f = {
|
||||||
|
input = ts_input({ outer = '@call.outer', inner = '@call.inner' })
|
||||||
|
},
|
||||||
|
}
|
||||||
|
})
|
38
common/home/neovim/plugins/neotree.lua
Normal file
38
common/home/neovim/plugins/neotree.lua
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
-- Override netrw
|
||||||
|
vim.g.loaded_netrw = 0
|
||||||
|
vim.g.loaded_netrwPlugin = 0
|
||||||
|
|
||||||
|
require('neo-tree').setup({
|
||||||
|
close_if_last_window = true,
|
||||||
|
enable_refresh_on_write = true,
|
||||||
|
|
||||||
|
window = {
|
||||||
|
width = 22,
|
||||||
|
},
|
||||||
|
|
||||||
|
filesystem = {
|
||||||
|
use_libuv_file_watcher = true,
|
||||||
|
group_empty_dirs = true,
|
||||||
|
|
||||||
|
filtered_items = {
|
||||||
|
visible = false,
|
||||||
|
hide_dotfiles = false,
|
||||||
|
hide_gitignored = true,
|
||||||
|
hide_by_name = {},
|
||||||
|
hide_by_pattern = {},
|
||||||
|
always_show = {},
|
||||||
|
never_show = {},
|
||||||
|
never_show_by_pattern = {},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
|
||||||
|
source_selector = {
|
||||||
|
winbar = true,
|
||||||
|
statusline = false
|
||||||
|
},
|
||||||
|
|
||||||
|
follow_current_file = {
|
||||||
|
enabled = true,
|
||||||
|
leave_dirs_open = true,
|
||||||
|
}
|
||||||
|
})
|
11
common/home/neovim/plugins/neotree.vim
Normal file
11
common/home/neovim/plugins/neotree.vim
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
" Auto open Neo-Tree on big enough window
|
||||||
|
function! OpenTree() abort
|
||||||
|
if &columns > 100
|
||||||
|
Neotree show
|
||||||
|
Neotree close
|
||||||
|
Neotree show
|
||||||
|
endif
|
||||||
|
lua MiniMap.open()
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
autocmd VimEnter * call OpenTree()
|
13
common/home/neovim/plugins/snippets.vim
Normal file
13
common/home/neovim/plugins/snippets.vim
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
" use vscode keybinds for snippets completion
|
||||||
|
inoremap <silent><expr> <TAB>
|
||||||
|
\ coc#pum#visible() ? coc#_select_confirm() :
|
||||||
|
\ coc#expandableOrJumpable() ? "\<C-r>=coc#rpc#request('doKeymap', ['snippets-expand-jump',''])\<CR>" :
|
||||||
|
\ CheckBackspace() ? "\<TAB>" :
|
||||||
|
\ coc#refresh()
|
||||||
|
|
||||||
|
function! CheckBackspace() abort
|
||||||
|
let col = col('.') - 1
|
||||||
|
return !col || getline('.')[col - 1] =~# '\s'
|
||||||
|
endfunction
|
||||||
|
|
||||||
|
let g:coc_snippet_next = '<tab>'
|
21
common/home/neovim/plugins/treesitter.vim
Normal file
21
common/home/neovim/plugins/treesitter.vim
Normal file
|
@ -0,0 +1,21 @@
|
||||||
|
lua << EOF
|
||||||
|
|
||||||
|
require('nvim-treesitter.configs').setup({
|
||||||
|
highlight = { enable = true },
|
||||||
|
indent = { enable = true },
|
||||||
|
})
|
||||||
|
|
||||||
|
require('treesitter-context').setup({
|
||||||
|
enable = true,
|
||||||
|
max_lines = 3,
|
||||||
|
min_window_height = 20,
|
||||||
|
})
|
||||||
|
|
||||||
|
vim.filetype.add({
|
||||||
|
pattern = { [".*/hypr/.*%.conf"] = "hyprlang" },
|
||||||
|
})
|
||||||
|
|
||||||
|
EOF
|
||||||
|
|
||||||
|
" Add line under context
|
||||||
|
hi TreesitterContextBottom gui=underline guisp=Grey
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue